Score:0

How to route certain traffic in OpenVPN from one client through another client?

la flag

Scenario

ClientA (Windows 10) and ClientB (Raspberry Pi OS) are both connected via OpenVPN to ServerA (Debian 10) over the internet. The OpenVPN network is 10.0.0.0/24.

Machine OpenVPN IP
ServerA 10.0.0.1
ClientA 10.0.0.2
ClientB 10.0.0.3

ClientB has access to network 192.168.0.0/24. 192.168.0.250 runs a webserver.

Goal

All internet traffic of ClientA goes through ServerA's internet connection. All traffic of ClientA to 192.168.0.0/24 goes through ClientB.

Current (faulty) setup

What works

ClientA is a client of ServerA's OpenVPN service and routes all traffic through the VPN.
ClientB is a client of ServerA's OpenVPN service.
ClientA and ClientB can ping each other.
ServerA routes all internet traffic of ClientA through its own internet connection.
ServerA routes all traffic from ClientA to 192.168.0.0/24 to ClientB.

What doesn't work:

ClientA cannot establish connection to any machine on 192.168.0.0/24. It seems ClientB is not routing the traffic or performing the NAT accordingly.

Setup

ClientA

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1      192.168.1.6     25
          0.0.0.0        128.0.0.0         10.0.0.1         10.0.0.2    281
      192.168.0.0    255.255.255.0         10.0.0.1         10.0.0.2    281
         10.0.0.0    255.255.255.0         On-link          10.0.0.2    281
         10.0.0.2  255.255.255.255         On-link          10.0.0.2    281
       10.0.0.255  255.255.255.255         On-link          10.0.0.2    281
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
        128.0.0.0        128.0.0.0         10.0.0.1         10.0.0.2    281
          x.x.x.x  255.255.255.255      192.168.1.1      192.168.1.6    281 # ServerA public IP
      192.168.1.0    255.255.255.0         On-link       192.168.1.6    281
      192.168.1.6  255.255.255.255         On-link       192.168.1.6    281
    192.168.1.255  255.255.255.255         On-link       192.168.1.6    281
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link          10.0.0.2    281
        224.0.0.0        240.0.0.0         On-link       192.168.1.6    281
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link          10.0.0.2    281
  255.255.255.255  255.255.255.255         On-link       192.168.1.6    281
===========================================================================
Persistent Routes:
  None
tracert 192.168.0.250

Tracing route to 192.168.0.250 over a maximum of 30 hops

  1    72 ms    71 ms    73 ms  10.0.0.3
  2     *        *        *     Request timed out.
  3     *        *        *     Request timed out.
  4  ^C

There is no firewall on ClientA.

ServerA

cat /proc/sys/net/ipv4/ip_forward

1
ifconfig -a (shortened)

ens3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet x.x.x.x  netmask 255.255.252.0  broadcast x.x.x.255

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.0.0.1  netmask 255.255.255.0  destination 10.0.0.1
ip route show

default via x.x.x.x dev ens3
192.168.0.0/24 via 10.0.0.3 dev tun0
10.0.0.0/24 dev tun0 proto kernel scope link src 10.0.0.1
x.x.x.0/22 dev ens3 proto kernel scope link src x.x.x.x
x.x.x.x dev ens3 scope link
nft list ruleset

table ip filter {
        chain INPUT {
                type filter hook input priority 0; policy accept;
                iifname "tun0" counter packets 5003 bytes 808157 accept
        }

        chain FORWARD {
                type filter hook forward priority 0; policy accept;
                ct state established,related counter packets 1565233 bytes 1274112205 accept
                iifname "tun0" counter packets 23326 bytes 1702134 accept
                iifname "ens3" oifname "tun0" ct state established,related counter packets 0 bytes 0 accept
                iifname "tun0" oifname "ens3" ct state established,related counter packets 0 bytes 0 accept
        }

        chain OUTPUT {
                type filter hook output priority 0; policy accept;
        }
}
table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority -100; policy accept;
        }

        chain INPUT {
                type nat hook input priority 100; policy accept;
        }

        chain POSTROUTING {
                type nat hook postrouting priority 100; policy accept;
                ip saddr 10.0.0.0/24 oifname "ens3" masquerade
                oifname "ens3" ip saddr 10.0.0.0/24 counter packets 0 bytes 0 masquerade
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
        }
}
traceroute 192.168.0.250

traceroute to 192.168.0.250 (192.168.0.250), 30 hops max, 60 byte packets
 1  10.0.0.3 (10.0.0.3)  46.951 ms  48.232 ms  48.180 ms
 2  * * *
 3  * * *
 4  *^C

ClientB

cat /proc/sys/net/ipv4/ip_forward

1

ClientB has its internet connection and connection to 192.168.0.0/24 on the same interface. The traffic to both works flawlessly from ClientB.

ifconfig -a (shortened)

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.178.70  netmask 255.255.255.0  broadcast 192.168.178.255

eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.249  netmask 255.255.255.0  broadcast 192.168.0.255

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.0.0.3  netmask 255.255.255.0  destination 10.0.0.3
ip route show

0.0.0.0/1 via 10.0.0.1 dev tun0
default via 192.168.178.1 dev eth0 proto dhcp src 192.168.178.70 metric 202
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.249
10.0.0.0/24 via 10.0.0.1 dev tun0
128.0.0.0/1 via 10.0.0.1 dev tun0 # no clue where this comes from
x.x.x.x via 192.168.178.1 dev eth0
192.168.178.0/24 dev eth0 proto dhcp scope link src 192.168.178.70 metric 202

This is how I setup iptables:

iptables -A INPUT -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0:1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0:1 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0:1 -j MASQUERADE
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -L -n -v

Chain INPUT (policy ACCEPT 6619 packets, 2460K bytes)
 pkts bytes target     prot opt in     out     source               destination
  362 22004 ACCEPT     all  --  tun0   *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    4   240 ACCEPT     all  --  tun0   *       0.0.0.0/0            0.0.0.0/0            # 4 ICMP (ping) packets have been received, but not forwarded correctly
    0     0 ACCEPT     all  --  tun0   eth0:1  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  eth0:1 tun0    0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT 6849 packets, 2466K bytes)
 pkts bytes target     prot opt in     out     source               destination
  280 52688 ACCEPT     all  --  *      tun0    0.0.0.0/0            0.0.0.0/0
traceroute 192.168.0.250

traceroute to 192.168.0.250 (192.168.0.250), 30 hops max, 60 byte packets
 1  192.168.0.250 (192.168.0.250)  1.630 ms  1.479 ms  0.927 ms

Assumption

I assume that ClientB is not routing the traffic or performing the NAT correctly.

I've played around with different iptables settings on ClientB, but couldn't get it working.

Any ideas?

Score:0
la flag

I finally found the solution.

The problem was, that iptables doesn't support virtual network adapters (in my case eth0:1).
So, instead of configuring iptables on ClientB like this

...
iptables -A FORWARD -i tun0 -o eth0:1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0:1 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0:1 -j MASQUERADE
...

it had to be configured like this (without the extension for the virtual adapter :1):

...
iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
...

Now the traffic gets routed as intended. Hope this helps someone else.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.