一、透明代理概述
根据百度百科的资料:透明代理的意思是客户端根本不需要知道有代理服务器的存在,它改变你的 request fields(报文),并会传送真实IP,多用于路由器的NAT转发中。
透明代理技术中的透明是指客户端感觉不到代理的存在,不需要在浏览器中设置任何代理,客户只需要设置缺省网关,客户的访问外部网络的数据包被发送到缺省网关,而这时缺省网关运行着一个代理服务器,数据实际上被被重定向到代理服务器的代理端口(如8080),即由本地代理服务器向外请求所需数据然后拷贝给客户端。理论上透明代理可以对任何协议通用。
二、实验目标
如上图所示,本实验的目标主要是将一个主机 B 配置成一个 TCP 透明代理服务器,使不在同一个网段的客户主机 A 和客户主机 B 可以通过这个代理服务器进行通信,且客户主机 A、C 对这个透明代理服务器是无感知的,即它们是直接将数据包发送给对方的真实 IP 的。
- 主机 A 直接发送数据给不同网段的 IP (
192.168.2.12
) ,主机 B(即代理服务器)可以将数据转发到目的地。 - 同样,主机 C 到主机 A 的方向也成立。
注:
- 上述实验所采用的系统均为 Ubuntu。
- 三台机器之间需要通过交换机连接,不能直连。
三、环境搭建
在本实验中,要实现 TCP 透明代理功能,首先需要配置好路由转发功能。
3.1 代理服务器配置
3.1.1 开启内核路由转发
首先,在作为代理服务器的主机 B 上开启内核路由转发功能。
-
打开
/etc/sysctl.conf
文件,在文件中添加如下配置:net.ipv4.ip_forward = 1
-
在终端中输入如下命令,使配置生效:
sysctl -p
如此,主机 B 的内核路由转发功能便被开启了。
3.1.2 配置转发规则
接下来,需要配置作为代理服务器的主机 B 的转发规则。
从我们上面的目标的示意图来看,要求代理服务器 B 可以将 192.168.1.20
的数据包转发到 192.168.2.12
,同时还要求数据包也可以反着转发。 因此,我们需要配置代理服务器 B 可以将 1 网段的数据转发到 2 网段,同样也可以将 2 网段的数据转发到 1 网段。
-
配置将 1 网段的数据转发到 2 网段的规则,即数据从 eth0 网卡入,从 eth1 网卡出:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 192.168.2.0/24 -o eth1 -j MASQUERADE
-
配置将 2 网段的数据转发到 1 网段的规则,即数据从 eth1 网卡入,从 eth0 网卡出:
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -d 192.168.1.0/24 -o eth0 -j MASQUERADE
3.2 客户主机配置
3.2.1 客户主机 A 配置
-
连接客户主机 A 与代理服务器 B
首先需要将客户主机 A 通过交换机与代理服务器 B 连接,然后将客户主机 A 的 IP 设置为
192.168.1.20
(不要求必须是这个,只要与代理服务器 B 的 eth0 网卡在同一个网段即可)。上述步骤完成之后,在客户主机 A 上 Ping 一下代理服务器 B 的 eth0 网卡看看能否连通,只有能够连通才可以进行下面的步骤。
-
添加静态路由
在主机 A 的终端上输入如下命令以添加静态路由:
route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.21
上述命令的作用是:所有发往
192.168.2.0
地址段的 IP 数据包,全部由192.168.1.21
路径转发。添加静态路由之后,在客户主机 A 上 Ping 一下代理服务器的 eth1 网卡,看看静态路由是否配置成功。
3.2.2 客户主机 C 配置
-
连接客户主机 C 与代理服务器 B
同样,主机 C 与主机 B 也需要交换机连接,然后将主机 C 的 IP 设置为
192.168.2.12
(只要与主机 B 的eth1 在同一个网段即可)。同样,在主机 C 上 Ping 一下主机 B 看能否连通。
-
添加静态路由
在主机 C 上输入如下命令以添加静态路由:
route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.2.11
上述命令的作用是:所有发往
192.168.1.0
地址段的 IP 数据包,全部由192.168.2.11
路径转发。同样,在主机 C 上 Ping 一下代理服务器 B 的 eth0 网卡,能够连通则说明静态路由配置成功。
四、实现 TCP 透明代理
本实验中采用开源项目 tproxy-example ,将其运行在代理服务器 B 上来实现 TCP 透明代理功能。
按照下面的步骤来测试透明代理:
先说一下测试步骤:
- 首先在主机 C 上运行自定义的 server 程序,该程序可以将从主机 A 收到的数据回显给主机 A。
- 然后在代理服务器 B 上运行开源项目 tproxy-example ,该程序可以将主机 A 的数据转发给主机 C,同样也可以将主机 C 的数据转发到主机 A。
- 最后在主机 A 上运行自定义的 client 程序,该程序可以发送自定义的信息到主机 C。
如果一切配置正常,那么在客户主机 A 上运行的 client 程序发送的文本消息可以顺利发送到客户主机 C 的 server 上,同时主机 C 会将数据回显到主机 A 上。
最后附上我自定义的 server 和 client 的代码。
-
server.cpp
/* 使用 epoll 的服务端程序 */ #include <iostream> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <strings.h> #include <sys/epoll.h> #include <fcntl.h> #define SERVER_PROT 9876 #define MESSAGE_LEN 1024 #define MAX_EVENTS 20 #define TIMEOUT 500 int main(int argc, char* argv[]){ int socket_fd, accept_fd; int on = 1; int ret = -1; struct sockaddr_in localaddr, remoteaddr; socklen_t addrlen; char recv_buf[1024]; int epoll_fd; struct epoll_event ev, events[MAX_EVENTS]; int event_number; int flags; // 1. 创建套接字文件描述符,并设置 socket 选项 socket_fd = socket(AF_INET, SOCK_STREAM, 0);