network-programmingroutesvpntun

kernel not echo ICMP ping package written to tun device?


I am trying to write a vpn server on my vps. I have setup the tun interface < tun2 > and the packages that received from network can be written to tun device on the server. However when I test the connectivity by ping command from client, there is no ICMP response package from server's kernel. What did I miss?

this is the topology:

┼─────────────────┼                              ┼─────────────────┼
│     client      │                              │     server      │
┼─────────────────┼                              ┼─────────────────┼
│tun0:            │──────────────TCP─────────────│tun2:            │
│  192.168.255.2  │                              │  192.168.255.1  │
│                 │                              │                 │
┼─────────────────┼                              ┼─────────────────┼

This is the server's configure:

seven@server:~$ ifconfig tun2
tun2      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
      inet addr:192.168.255.1  P-t-P:192.168.255.2  Mask:255.255.255.255
      UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
      RX packets:3 errors:0 dropped:0 overruns:0 frame:0
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:500
      RX bytes:252 (252.0 B)  TX bytes:0 (0.0 B)


seven@server:~$ ip route
10.77.88.5 dev tun0  proto kernel  scope link  src 10.77.88.1
10.77.99.2 dev tun1  proto kernel  scope link  src 10.77.99.1
192.168.255.2 dev tun2  proto kernel  scope link  src 192.168.255.1
10.77.99.0/24 via 10.77.99.2 dev tun1
default dev venet0  scope link

I can see the ICMP echo requests are sent to tun2 on server by tcpdump, but no response:

seven@server:~$ sudo tcpdump -n -vvv -i tun2
tcpdump: listening on tun2, link-type RAW (Raw IP), capture size 262144 bytes
11:15:08.046578 IP (tos 0x0, ttl 64, id 63330, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.255.2 > 192.168.255.1: ICMP echo request, id 7392, seq 1, length 64
11:15:09.073521 IP (tos 0x0, ttl 64, id 63527, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.255.2 > 192.168.255.1: ICMP echo request, id 7392, seq 2, length 64
11:15:10.097919 IP (tos 0x0, ttl 64, id 63632, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.255.2 > 192.168.255.1: ICMP echo request, id 7392, seq 3, length 64

looks like the routing on server is correct:

seven@vps:~$ ip route get 192.168.255.2
192.168.255.2 dev tun2  src 192.168.255.1
    cache  mtu 1500 hoplimit 64

which means if a ICMP response is generated by kernel, it can be routed to tun2? So my guess is, kernel did not response to the ICMP pings?

this is client's configure:

seven@client:~$ ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
      inet addr:192.168.255.2  P-t-P:192.168.255.1  Mask:255.255.255.255
      inet6 addr: fe80::c940:cd18:2f2c:9206/64 Scope:Link
      UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0
      TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:500
      RX bytes:0 (0.0 B)  TX bytes:492 (492.0 B)

seven@client:~$ ip route
default via 192.168.1.1 dev enp4s0  proto static  metric 100
169.254.0.0/16 dev docker_gwbridge  scope link  metric 1000 linkdown
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
172.18.0.0/16 dev docker_gwbridge  proto kernel  scope link  src 172.18.0.1 linkdown
192.168.1.0/24 dev enp4s0  proto kernel  scope link  src 192.168.1.5  metric 100
192.168.255.1 dev tun0  proto kernel  scope link  src 192.168.255.2

Solution

  • After hours of debugging, it is turn out a code bug: I don't have IFF_NO_PI flag set when openning tun device, but I accidentally ntohs the flag and proto fields before sending it thru network, so the proto was changed from \x08\x00 to \x00\x08. When the package was written into tun, kernel actually don't treat it as IPv4 package and ignored.