对透明代理,需要使用几个功能,首先IP_TRANSPARENT,内核2.6.28就已经支持, centos6.3及以上是肯定支持的。
它的作用是,如果某个ip在本机不存在,监听0.0.0.0一样可以收到数据,而发送的时候,可以bind任意一个不存在的ip(当然这个bind你使用netstat是看不见的),这样你就可以伪造任意客户端的报文。
代码也很简单
监听增加
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value))
发送增加
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) if(getsockname( s->client_sock , (struct sockaddr *)&server_addr, &addrlen ) ) { http_close_stream(s,"adns_transparent_client"); return; }
这里获取真正的服务器地址,写入server_addr
if (bind(s->server_sock, (struct sockaddr*)&s->client_addr, addrlen ) == -1) { http_close_stream(s, "adns_transparent_bind"); return; }
绑定客户端地址(虽然本机没有这个ip)
r = connect_nonb(sock, (struct sockaddr *)&server_addr);
连接真正的服务器地址。
当然如果想收到报文,还是需要做一些操作的,比如我们收到路由器转发的80端口的请求。
然后
iptables -t mangle -N DIVERT iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT iptables -t mangle -A DIVERT -j MARK --set-mark 1 iptables -t mangle -A DIVERT -j ACCEPT ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100 iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 81
注意你的服务器的监听端口改成非80,比如81端口,这样就能收到数据了。
可是我发现能收到数据,握手成功,但是服务器像真正的源站发送的握手又被交换机给转发回来了。
因为对于交换机来说,客户端发的握手和服务器发的握手在ip层面都一模一样,源地址和目的地址都相同。
这里需要对交换机做一个限制,对于服务器mac地址的包,走默认路由。
如下是路由器配置
10.0.30.100是客户端
10.0.3.15是服务器
ip access-list extended ppc permit tcp host 10.0.30.100 any eq www ip access-list extended ppc-15 permit tcp any eq www host 10.0.30.100 route-map ppc-15 permit 10 match ip address ppc-15 set ip next-hop 10.0.3.15 ! route-map ppc permit 10 match ip address ppc set ip next-hop 10.0.3.15 ! route-map ppc permit 20 interface Vlan300 ip address 10.0.30.1 255.255.255.0 ip policy route-map ppc interface GigabitEthernet0/24 no switchport ip address 10.0.0.2 255.255.255.252 no ip proxy-arp ip policy route-map ppc-15