Trojan-Plus-Group / trojan-plus

More Experimental Effective Features for Trojan
GNU General Public License v3.0
83 stars 21 forks source link

Don't quiet understand how ICMP proxy works #1

Closed leiless closed 4 years ago

leiless commented 4 years ago

Hi, @yuchting, I'm getting interested in how ICMP proxy works.

..., because it needs iptables transfer icmp message to local system, ... https://github.com/Trojan-Plus-Group/trojan-plus/wiki/Can-we-proxy-ICMP-message-(To-transfer-ping)#configure

I try to manipulate iptables so that ICMP echo requests can be intercepted by user space program, and I can manually send it out, yet the

ip route add local 0/0 dev lo table 100
ip rule add fwmark 1 lookup 100

...
iptables -t mangle -N ICMP_PROXY

iptables -t mangle -A ICMP_PROXY -p icmp -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p icmp -j ICMP_PROXY

Not working, I cannot capture any ICMP echo requests from user space program, the ICMP echo requests seems not route to local system.

And I still not quite understand how ICMP proxy works in client/server.

Could you explain more in details? I'm newbie to networking programming...

leiless commented 4 years ago

I've used https://www.cs.dartmouth.edu/~sergey/cs60/lab3/icmp4-rawrecv.c to receive ICMP echo request(nothing is captured) https://www.cs.dartmouth.edu/~sergey/cs60/lab3/lab3.pdf

yuchting commented 4 years ago

@leiless

Did you use tcpdump to capture icmp packet?

If you configure iptables correctly, icmp message will be transfer to localhost( gateway ), otherwise it will be forwarded outside localhost.

As you said, you might think iptables can transfer something to user space(out of kernel), it's wrong thought model, iptables just transfers those icmp messages before routing to localhost, then localhost system will capture this message.

I give you some example if you set :

terminal on the left is my pi in local network, the other terminal on the right is my gateway, when you iptables configure is correctly, tcpdump can capture icmp message which destination address is not gateway:

image

if you haven't correct iptables configures, tcpdump won't capture it.

after tcpdump on your gateway system can icmp message with outside destination address, then wirte code.

leiless commented 4 years ago

Did you use tcpdump to capture icmp packet?

Yes, yet the user space demo program cannot receive any packet, tcpdump can capture it. Tested on dev machine, router not yet tested previously.

@yuchting, After I followed your advice:

Router setup

sudo ip route add local 0/0 dev lo table 100
sudo ip rule add fwmark 1 lookup 100

sudo iptables -t mangle -N ICMP_PROXY
sudo iptables -t mangle -A ICMP_PROXY -p icmp -j MARK --set-mark 1
sudo iptables -t mangle -A PREROUTING -p icmp -j ICMP_PROXY
$ ip route show table 100
local default dev lo scope host

$ ip rule list
0:  from all lookup local 
32765:  from all fwmark 0x1 lookup 100 # Our rule
32766:  from all lookup main 
32767:  from all lookup default

$ sudo iptables -t mangle -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
ICMP_PROXY  icmp --  0.0.0.0/0            0.0.0.0/0           

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain ICMP_PROXY (1 references)
target     prot opt source               destination         
MARK       icmp --  0.0.0.0/0            0.0.0.0/0            MARK set 0x1

Which just as https://github.com/Trojan-Plus-Group/trojan-plus/wiki/Can-we-proxy-ICMP-message-(To-transfer-ping)#configure described.

Client machine

Before iptables

$ ping baidu.com -c1
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=48 time=30.6 ms

--- baidu.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 30.563/30.563/30.563/0.000 ms

After iptables

$ ping baidu.com -c1
PING baidu.com (39.156.69.79) 56(84) bytes of data.

--- baidu.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

Route machine

Before iptables

$ sudo tcpdump icmp -i enx000ec6b2d0ae -vvv
tcpdump: listening on enx000ec6b2d0ae, link-type EN10MB (Ethernet), capture size 262144 bytes
09:08:02.847475 IP (tos 0x0, ttl 63, id 39123, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.100 > 220.181.38.148: ICMP echo request, id 78, seq 1, length 64
09:08:02.875307 IP (tos 0x0, ttl 49, id 39123, offset 0, flags [DF], proto ICMP (1), length 84)
    220.181.38.148 > 192.168.100.100: ICMP echo reply, id 78, seq 1, length 64

Which the tcpdump can capture the echo request/reply.

After iptables

$ sudo tcpdump icmp -i enx000ec6b2d0ae -vvv
tcpdump: listening on enx000ec6b2d0ae, link-type EN10MB (Ethernet), capture size 262144 bytes
09:12:09.530039 IP (tos 0x0, ttl 63, id 31938, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.100 > 39.156.69.79: ICMP echo request, id 80, seq 1, length 64

Now, tcpdump now can only capture the echo request, and it means it works? since we need to use user space program to capture the incoming echo request, and we need to send to our proxy, and write the echo reply back? So a whole round trip communication can be completed?

leiless commented 4 years ago

So the whole idea is to use iptables to transfer ICMP messages issued by DHCP clients to gateway(router), when router received the echo requests, send it out to the ICMP proxy, and write back echo reply when the proxy replied?

Since the ICMP messages will routed to the gateway, so we basically cannot capture it at local machine itself and send it out manually by ourselves? As you aforementioned:

As you said, you might think iptables can transfer something to user space(out of kernel), it's wrong thought model, iptables just transfers those icmp messages before routing to localhost, then localhost system will capture this message.

yuchting commented 4 years ago

@leiless

Sorry for this delay.

Now, tcpdump now can only capture the echo request, and it means it works? since we need to use user space program to capture the incoming echo request, and we need to send to our proxy, and write the echo reply back? So a whole round trip communication can be completed?

Yes, your understanding is correct. your iptables config is right.

So the whole idea is to use iptables to transfer ICMP messages issued by DHCP clients to gateway(router), when router received the echo requests, send it out to the ICMP proxy, and write back echo reply when the proxy replied?

Yes.

So let me show how capture this ICMP message with (192.168.100.100 > 220.181.38.148): https://github.com/unpbook/unpv13e/tree/master/icmpd

err, I haven't any other things need to say, the codes already show clearly: https://github.com/unpbook/unpv13e/blob/master/icmpd/icmpd.c

if you want to know how boost do it, here is an example: https://github.com/Trojan-Plus-Group/trojan-plus/blob/dev/src/core/icmpd.cpp

leiless commented 4 years ago

Thanks for your patient replies. :-D

I have no question by now, I'll open a new issue if I have one. Thx anyway!