2

I'm writing a program that sends data through a tun interface. I'm trying to send IP packets to the world. I have all the TCP/IP stack working: It creates a valid TCP/IP packet ready to be sent, I just need to send it.

I know how to create a tun interface, but how do I make this tun interface relay IP packets to the world and receive them back?

I want to send IP packets that connect to google.com and receive the HTTP response.

UPDATE. After Hauke Laging's answer I tried:

user@orwell2:~$ sudo route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.137.0.5      0.0.0.0         UG    0      0        0 eth0
10.137.0.5      0.0.0.0         255.255.255.255 UH    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
user@orwell2:~$ sudo nano /etc/sysctl.conf
user@orwell2:~$ sudo sysctl -p
fs.inotify.max_user_watches = 524288
net.ipv4.ip_forward = 1
user@orwell2:~$ sudo openvpn --mktun --dev tun1 --user $USER
Tue May 26 18:45:09 2020 TUN/TAP device tun1 opened
Tue May 26 18:45:09 2020 Persist state set to: ON
user@orwell2:~$ sudo ip link set tun1 up
user@orwell2:~$ sudo ip addr add 192.168.0.2/24 dev tun1
user@orwell2:~$ sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
user@orwell2:~$ sudo iptables -A FORWARD -i tun1 -o eth0 -j ACCEPT
user@orwell2:~$ ping -I tun1 google.com
PING google.com (172.217.28.238) from 192.168.0.2 tun1: 56(84) bytes of data.
^C
--- google.com ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6179ms

user@orwell2:~$ sudo iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
    0     0 ACCEPT     all  --  *      vif+    0.0.0.0/0            0.0.0.0/0           
    6   312 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0           
  102  6268 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

As you can see, I cannot ping google.com through tun1. Then I printed the masquerade options, but I don't know if I need to add one for tun1 or not.

12
  • "I'm writing a program that sends data through a tun interface". Where is the program creating packets? You're trying to send packets to tun1 here, not receiving packets from tun1 (and from this program). Without a process using the other side of this interface, consider this interface isn't connected ("NO-CARRIER").
    – A.B
    May 26, 2020 at 21:51
  • @A.B I understand. I want to do something to my tun interface so it does indeed send packets to the world (and also receive them, since my program also reads from tun1) May 26, 2020 at 21:57
  • @A.B I know that tap interfaces are for ethernet and tun for ip. I know OpenVPN creates a tun interface (or tap, but lets talk about tun) where it writes IP packets and receives IP packets. These packets end up in another computer. This is what I know. So, I need to create a tun interface myself to send packets to the internet so I can test my tcp/ip stack. It already works with tap but Im porting it to work with tun May 26, 2020 at 22:03
  • I can just retell the same: to test your tcp/ip stack from a process, this process must be running and using the tun interface (with the specific tun/tap api to do this). I didn't see you running a process in your setup.
    – A.B
    May 26, 2020 at 22:07
  • 1
    @A.B I just didnt fire my ip stack yet because I can't ping through my tun1 interface. If I cant ping, then it can't relay packets to the world May 26, 2020 at 22:08

2 Answers 2

4
+100

I believe that you need to proper local and remote address on the tunnel device you are creating in order to have packets created by your program relayed to the world.

According to the provided PCAP file, your program generates TCP/IP packets coming from address 192.168.69.1. That should be the remote address of the TUN device. My suggestion is to create the tunnel device and setup IP forwarding and the host firewall as following:

$ sudo ip tuntap add dev tun1 mode tun user `id -un`
$ sudo ip link set dev tun1 up
$ sudo ip addr add dev tun1 local 192.168.69.0 remote 192.168.69.1
$ sudo iptables -t filter -I FORWARD -i tun1 -o eth0 -j ACCEPT
$ sudo iptables -t filter -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
$ sudo sysctl net.ipv4.ip_forward=1
$ /path/to/your/packet/generator/program tun1

In ancient times, when people used to connect a modem device to the telephone line and dial the phone of an internet provider to establish connection to the internet, the pppd daemon used to be responsible to establish a point-to-point tunnel to the server located at the other end of the call. On those tunnels, the local address was the address assigned to the network interface being created in kernel network stack and the remote address was the local address of the other computer answering the phone call and, also, the address set as the default gateway in the local side.

For TUN virtual devices, your user-space program will act as the remote computer at the other side of the tunnel. Therefore, in order to have your program injecting IP packets to the kernel network stack, the program is supposed to generate packets with source address set to the tunnel remote address (192.168.69.1) and receive packets whose destination is set to the same address.

5
  • 1
    I can tweak the source IP of the packet in the IP stack so this is not a problem. I tried searching about "linux local and remote address" but didn't find anything. I'm trying to understand how routing works. The other commands I think I understand. You enabled forwarding from tun1 to eth0. But why a nat? Do you recommend something for me to read to understand about routing exactly like this? I've read some PDFs on google but they do not talk about these things May 28, 2020 at 5:50
  • Firstly, please feed my curiosity... Has my answer worked for you? :-) May 28, 2020 at 6:46
  • I suggested configuring NAT just like @Hauke Laging's answer because the router device with address 10.137.0.5 may not have a route informing that packets being address to 192.168.69.1 (the user-space program) shall be routed through your physical host. If you have control over that router's routing table, you will be able to get rid of the MASQUERADING target. May 28, 2020 at 6:47
  • Mind that a point-to-point network device works different from a broadcast-capable network device such as Ethernet and, also, that a TUN device is different to TAP device in that the former injects IP packets and the latter injects Ethernet frames. Then, I suggest reading the networking/tuntap.txt file inside Kernel documentation and test point-to-point tunnels in practice using SSH (ssh -o Tunnel=point-to-point -w 1:1 <remote-host>). May 28, 2020 at 8:30
  • Yes, it WORKED! Thank you, I'm gonna digest the information you posted. Thank you so much! Jun 1, 2020 at 4:29
1

You must configure routing and (maybe) the packet filter (firewall) on the system.

  1. Set net.ipv4.ip_forward to 1 (sysctl for a permanent configuration)
  2. If the firewall does not yet allow forwarding then you need someting like

    iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
    
  3. You may also need MASQUERADING/SNAT so that your gateway knows that the packets came from this system (see iptables -t nat -nvL POSTROUTING)

8
  • Can you take a look at my update in the question? I tried 1 and 2 but don't know if 3 is already done. Can't ping google.com through my tun1 May 26, 2020 at 21:49
  • @GuerlandoOCs route is deprecated. You should get used to using ip route instead. I do not understand the aim of ping -I tun1 google.com. Your question was about a program that writes data to a tun interface. From the host's perspective that is input data. Using ping and the tun as output interface is something completely different. You can use an openvpn connection for testing. The ping must be executed on the other system then. May 26, 2020 at 22:51
  • I was using ping just to simulate my ip stack. I need to know first if the world is reacheable through tun1. If I can ping google through tun1 then I can use my ip stack through tun1, can't I? May 26, 2020 at 23:00
  • @GuerlandoOCs Of course, nothing is reachable via tun1. The interface is not connected. The Internet is reachable via eth0 only. May 26, 2020 at 23:03
  • Yes, but I want to make tun1 reach the internet. I want to use a tun device to connect to the internet. May 26, 2020 at 23:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .