2

I have a physical network with a Linux server (Ubuntu 16.04, kernel 4.13) and several gadgets on it. Each gadget has the same unchangeable static IP, e.g. 192.168.0.222/24. I would like to communicate with all these gadgets via an arbitrary IP protocol (e.g. ICMP ping or a custom UDP protocol)

Fortunately I have a managed network switch connecting the server and the gadgets. I've configured the switch to have a trunk port for the server and access ports for each gadget, each on a different VLAN (VIDs 11, 12, etc).

I have added 8021q to /etc/modules and set up VLAN entries in /etc/network/interfaces:

auto eno2 # For switch management interface
iface eno2 inet static
  address 192.168.2.2/24

auto eno2.11 # Gadget 1 (only)
iface eno2 inet static
  address 192.168.0.1/24

#auto eno2.12 # Gadget 2 - disabled
#iface eno2 inet static
#  address 192.168.0.1/24

With the entries as shown above, I can communicate with gadget 1 (e.g. ping 192.168.0.222) and don't see any traffic from gadget 2.

But I'd like to be able to communicate with all gadgets at the same time, and be able to distinguish one from the other. They don't need to talk to each other. I was thinking for each gadget I could create a unique host IP and subnet, e.g.

Host IP & subnet    "Fake" gadget IP     Actual gadget IP    VLAN Interface
192.168.101.1/24    192.168.101.222      192.168.0.222       eno2.11
192.168.102.1/24    192.168.102.222      192.168.0.222       eno2.12

I'd use iptables or nftables to handle the translation in each direction. Then I could ping 192.168.101.222 to reach gadget 1, and ping 192.168.102.222 to reach gadget 2. From each gadget's point of view, its own IP would still be 192.168.0.222 and it would see the ICMP echo requests coming from 192.168.0.1.

This seems like a somewhat unusual variant on NAT. Note the traffic with the "fake" IPs doesn't need to (and shouldn't) leave the server - we're not forwarding to something else on the network.

  1. Is this a reasonable approach to the problem?
  2. How do I set up /etc/network/interfaces and iptables or nftables to achieve this?
1
  1. Yes, it's reasonable.

  2. Unfortunately, Linux DNAT ("destination-rewriting NAT") is restricted to the prerouting chain. This is a PITA in your case, because it means you either:

    (a). do the DNAT on your server, but then you can uses these addresses only from outside the server, not from the server itself; or

    (b). you artificially create the above situation by making a network namespace, connect the network namespace to the server main namespace with a veth-pair, and then do the DNAT inside the network namespace. This means all your VLAN interfaces also go inside the network namespace.

I have no idea why the Linux network people made it that way, but that's the way it is. A general method to just rewrite packets would have been really handy ...

Google for "network namespace" and "iptables DNAT", that should be enough to get you started (unless someone else with more time than me writes a step-by-step answer...)

1

I was able to achieve this with the following nftables ruleset (I had to build nft from source as v0.5 which ships with Ubuntu 16.04 doesn't support packet field mangling) :

table ip mytable {
        chain prerouting {
                type filter hook prerouting priority -300; policy accept;
                iifname "eno2.11" ip saddr 192.168.0.222 ip saddr set 192.168.101.222
                iifname "eno2.12" ip saddr 192.168.0.222 ip saddr set 192.168.102.222
                iifname "eno2.13" ip saddr 192.168.0.222 ip saddr set 192.168.103.222
        }

        chain output {
                type filter hook output priority -300; policy accept;
                ip daddr 192.168.101.222 ip daddr set 192.168.0.222
                ip daddr 192.168.102.222 ip daddr set 192.168.0.222
                ip daddr 192.168.103.222 ip daddr set 192.168.0.222
        }
}

and the following entries in /etc/network/interfaces:

auto eno2 # For switch management interface
iface eno2 inet static
  address 192.168.2.2/24

auto eno2.11
iface eno2.11 inet static
  address 192.168.101.1
  netmask 255.255.255.0

auto eno2.12
iface eno2.12 inet static
  address 192.168.102.1
  netmask 255.255.255.0

auto eno2.13
iface eno2.13 inet static
  address 192.168.103.1
  netmask 255.255.255.0

This doesn't "unmangle" the source IP of outgoing packets, i.e. the gadgets still see requests from the server as coming from 192.168.101.1, 192.168.102.1 etc rather than 192.168.0.1 - in my application this doesn't matter but it could probably be addressed with additional rules in the output chain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.