关于java代码使用iptables和squid的思考
前几天一个同事突然问我如何安装和配置iptables转发规则。沟通后发现他生产环境用的iptables,测试环境用的squid。我当时询问他,代理服务器发生变化了,代码不需要跟着调整吗。他说java代码不用改动,说之前已经这样做过一次。我感到很好奇,软件变化,代码居然不用调整,一直想不通,索性今天在自己电脑写个代码java利用iptables、squid访问nginx的demo,发现确实是这样。但是也可能不一样。测试分析记录如下:
一、环境配置
- 服务器1:192.168.182.129 安装iptables、squid。其中iptables配转发规则:所有到iptables 8080的tcp网络请求都网路地址转换为192.168.182.130:8080。配置如下
-
service iptables restart echo 1 > /proc/sys/net/ipv4/ip_forward iptables -F iptables -t nat -F iptables -t nat -A PREROUTING -p tcp -d 192.168.182.129 --dport 8080 -j DNAT --t o-destination 192.168.182.130:8080 iptables -t nat -A POSTROUTING -p tcp --destination 192.168.182.130 --dport 8080 -j MASQUERADE

squid增加8080端口开通。配置如下

- 服务器2:192.168.182.130 仅安装nginx。启动8080端口,并配置仅服务器1可访问nginx。这样此台服务器仅能通过代理服务器1进行访问。

二、测试java通过squid访问nginx
测试条件:、
服务器2:./sbin/nginx,启动nginx.
服务器1:systemctl stop iptables.service、systemctl start squid.service。启动squid且不启动iptables 。
java代码使用通过squid代理访问nginx服务器,代码样例如下:
package org.example;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
public class ProxyHttpClient {
public static void main(String[] args) {
try {
// 创建代理服务器配置
Proxy proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("192.168.182.129", 3128));
// 创建URL对象
URL url = new URL("http://192.168.182.130:8080/index.html");
// 打开连接并设置代理
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
// 设置请求方法
connection.setRequestMethod("GET");
// 添加请求头(如果需要)
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
// 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("HTTP Response Code: " + responseCode);
// 读取响应内容
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
// 输出响应
System.out.println("Response Body: " + response.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
其中// 创建代理服务器配置 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.182.129", 3128));这里的ip为squid服务器地址和端口。
// 创建URL对象
URL url = new URL("http://192.168.182.130:8080/index.html");为真正的请求的url地址,这里的地址为真正需要访问的地址或域名。
测试结果:java代码正常访问了nginx,并返回了响应信息。<!DOCTYPE html><html><h1>Welcome to nginx!-182.130</h1></html>

三、测试java通过iptables访问nginx
测试条件:
服务器1: systemctl stop squid.service停止squid进程并启动iptables并配置规则 。
java代码使用通过iptables代理访问nginx服务器,代码样例如下:
package org.example;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
public class ProxyHttpClient {
public static void main(String[] args) {
try {
// 创建代理服务器配置
Proxy proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("192.168.182.129", 8080));
// 创建URL对象
URL url = new URL("http://192.168.182.130:8080/index.html");
// 打开连接并设置代理
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
// 设置请求方法
connection.setRequestMethod("GET");
// 添加请求头(如果需要)
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
// 获取响应码
int responseCode = connection.getResponseCode();
System.out.println("HTTP Response Code: " + responseCode);
// 读取响应内容
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
// 输出响应
System.out.println("Response Body: " + response.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
/ 创建代理服务器配置
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("192.168.182.129", 8080));其中这里为iptables的地址和端口。
// 创建URL对象
URL url = new URL("http://192.168.182.130:8080/index.html");为真正的请求的url地址,这里的地址为真正需要访问的地址或域名。
测试结果:java代码正常访问了nginx,并返回了响应信息。<!DOCTYPE html><html><h1>Welcome to nginx!-182.130</h1></html>
测试结论:squid的代码确实可以适用于iptables,仅仅调整如下的代理机的ip和端口。
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("192.168.182.129", 8080));
思考:
iptables作为透明代理,工作在网络层和传输层。squid工作在应用层。iptables对客户端是无感知,这意味着客户端完全可以直接访问iptables,而无需知道真实目的地址。这样java代码里其实无需利用代理,可以直接访问iptables。代码如下:
package org.example;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.util.EntityUtils;
import java.net.URI;
import java.net.URISyntaxException;
public class ApacheHttpClientWithProxy {
public static void main(String[] args) {
try {
// 创建代理服务器配置
org.apache.http.HttpHost proxy = new org.apache.http.HttpHost(
"192.168.182.129", 8080, "http");
// 创建带有代理设置的 HttpClient
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
HttpClient httpClient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
.build();
// 创建 HTTP 请求
HttpGet request = new HttpGet();
request.setURI(new URI("http://192.168.182.130:8080"));
// 执行请求
HttpResponse response = httpClient.execute(request);
// 处理响应
System.out.println("Status Code: " + response.getStatusLine().getStatusCode());
System.out.println("Response Body: " +
EntityUtils.toString(response.getEntity()));
} catch (URISyntaxException | java.io.IOException e) {
e.printStackTrace();
}
}
}
这里不再需要代理服务器类的实例Proxy,也不需要知道真实目的地址。仅仅把iptables作为真实服务器访问。
// 创建代理服务器配置
org.apache.http.HttpHost proxy = new org.apache.http.HttpHost(
"192.168.182.129", 8080, "http");
测试结果:下图是结果,也是可以正常访问。验证了iptables是透明转发,客户端无需知道真实服务器的信息。

综上,对于http协议,使用squid的java代码可以适用于iptables机器,但使用iptables的java代码不一定适用于squid。
按iptables的透明传输作用看,理论上使用iptables的java代码也不应该出现代理类对象new Proxy。
更多推荐
所有评论(0)