Iptables – Route all traffic through TUN interface

firewalliptableslinux-networkingroutingtun

I want all my traffic go through TUN interface.

Here is the flowchart

So, as you can see, the traffic is routed to TUN iface on 10.0.0.1 address from every program. Then, the program attached to the TUN does something with the packets, and then they are sent to my router on 192.168.1.1. Then they're routed across the Internet (for example, to my proxy server, but it doesn't actually matter that much for my problem).

So my goal is just to route traffic in that manner: $any_program <–> tunX <–> 192.168.1.1 (the router) (<--> thing means that traffic goes both in and out).

What I've did so far:

  1. First, I initialized tunX device with this function:
int tun_open(char *device)
{
    struct ifreq ifr;
    int fd, err;
    
    fd = open("/dev/net/tun", O_RDWR);
    if (fd == -1)
    {
        perror("opening /dev/net/tun");
        exit(1);
    }

    memset(&ifr, 0, sizeof (ifr));
    ifr.ifr_flags = IFF_TUN;
    strncpy(ifr.ifr_ifrn.ifrn_name, device, IFNAMSIZ);
    
    err = ioctl(fd, TUNSETIFF, (void *) &ifr);
    if (err == -1)
    {
        perror("ioctl TUNSETIFF");
        close(fd);
        exit(1);
    }

    return fd;
}

And then:

tunfd = tun_open("tun6");

Also, I enabled TUNSETPERSIST:

ioctl(tunfd, TUNSETPERSIST, 1) < 0);
  1. Then, I set up the device with following commands:
$ sudo ip addr add 10.0.0.1/24 dev tun6
$ sudo ip link set tun6 up                                                 

The program reads from tunfd and outputs the content. So far the only thing it reads is the following:

:B\{k
HOST: 239.255.255.250:1900
MAN: "ssdp:discover" 
MX: 1
ST: urn:dial-multiscreen-org:service:dial:1
USER-AGENT: Google Chrome/86.0.4240.198 Linux

%   N%*.%K%M%P%M%M%M%HP%,%M%*K%(aP%>O%M%LqP%@K%`P%P%Ҵ u@=U繤湤}=UoK%0=U

ssdp:discover? Why is this getting through my tun interface?

Output of route -n:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    600    0        0 wlp2s0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 tun6
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 wlp2s0
192.168.1.0     0.0.0.0         255.255.255.0   U     600    0        0 wlp2s0

I've been playing around with iptables and ip route programs, but I'm kind of a newbie in all these. As far as I understood, iptables doesn't actually route the packets, but filter them (I can be very wrong). So is there a way to route the packets with ip route?

Best Answer

Normal routing is based on destinations, not interfaces (unless you configure policy-based routing), therefore you need to route all outbound traffic to the 10.0.0.0/24 network:

ip route del default
ip route add default via 10.0.0.254

Actually it doesn't matter through which address in 10.0.0.0/24 you send it, it should reach your program.