I have the following situation on my host:

   ------------    -----------------                    eth0
   |   br0    |----|--o         o--|----o           o------o------ internet
   ------------    | veth3   veth6 | veth7         ppp0
                   |               |                      |   namespace   |

The routing configuration has been made using policy based routing. According to that, a packet sent from the host to the Internet (e.g., using ping) enters into my network through veth5, then goes in the namespace. From here, it is forwarded to veth7, then to ppp0 and reaches the Internet.

I want to configure a NAT rule that masquerades all the internal IP address using the ppp0 IP ( I have then added the rule using iptables

$ iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

However, my packets reaches eth0 without being masqueraded by the rule above.


The output of tcmpdump of vethW and eth0 is:

tcpdump_output_veth tcpdump_output_eth

Output of ip link:

ip link

Output of ip -4 addr:

ip -4 addr

Output of conntrack -L:

  • pinging Internet from the host

enter image description here

  • pinging Internet from the namespace

enter image description here

  • pinging Internet from the host,after adding a nat rule into the namespace

enter image description here

Does someone know the reason?

Thanks in advance for the help.

  • The rule looks good. Can you show the output of tcpdump both of vethW and eth0 (open two xterms) for a ping request + response? Any other rules in effect (iptables -S, iptables -t nat -S)?
    – dirkt
    Jul 18, 2017 at 10:56
  • I've just edited my question to show you the output of tcpdump. I don't have any other iptables rules.
    – ica
    Jul 19, 2017 at 9:53
  • Why are the packets on eth0 wrapped in PPPoE frames? Did you simplify your description of your setup? Also, there seems to be some bridging which you didn't mention. If you are running PPPoE over eth0, you need to do the masquerading on ppp0 (or whatever). Also, MASQ needs an IP address on the IF, if you have a funny setup, also try SNAT with explicit source. If none of this helps, please describe the missing details of your setup.
    – dirkt
    Jul 19, 2017 at 10:23
  • Then very likely the problem is in what was left out in the simplificaton. Please edit question with output of ip link and ip -4 addr of the main (outer) namespace so we can see what is actually going on.
    – dirkt
    Jul 19, 2017 at 10:57
  • Yes, I simplified the description of the setup and the masquerading is on ppp0. I'm using PPPoE so there is a ppp0 IF, I've edited the question. However, also using the explicit rule iptables -t nat -A POSTROUTING -o ppp0 -j SNAT --to it doesn't work.
    – ica
    Jul 19, 2017 at 10:58

1 Answer 1


Not an answer, but an attempt to narrow down the problem:

I reproduced a similar, somewhat simplified setup, and masquerading works fine. It looks like this:

+-----------+                             +----------+
|        o--|--o                  o--ptya |  ptyb--o |
|   veth0b  |  veth0a          ppp0       |     ppp0 |
|  |       | |
|           |                             |          |
|   ns0     |                             |   ns1    |
+-----------+                             +----------+

where the ppp-connection was made in the following way (the second pppd in the namespace ns1, of course):

socat PTY,link=/tmp/ptya PTY,link=/tmp/ptyb
sudo pppd `readlink /tmp/ptya` noauth nocrtscts xonxoff local maxfail 0 persist
sudo pppd `readlink /tmp/ptyb` noauth nocrtscts xonxoff local maxfail 0 persist


sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

From ns0, ping shows up on tcpdump -i ppp0 in the main namespace as

IP > ICMP echo request, id 23836, seq 1, length 64
IP > ICMP echo reply, id 23836, seq 1, length 64

so masquerading clearly works, and it's not the ppp-interface that's somehow acting up.

Things I would try next:

  • Replicate the socat/ppp setup on your server, and see if it works, or if there is something that differs that prevents it from working.

  • I originally tried to make a PPPoE-connection with the userspace pppoe, but this is sufficiently convoluted that the pppd spawned by pppoe-server kept dying on me, and I haven't yet figured out why. So if you can reduce your PPPoE configuration to a similar setup (and maybe tell me what you did), one could figure out if it's PPPoE that screws things up somehow.

  • While attempting this, I noticed that the scripts do a lot of stuff behind the scenes, if you are not careful: default routes, ip address asignments, iptables entry and whatnot. So I'd double check there are no funny iptables rules, routes or whatever in your setup, even if you didn't put them there.

  • You ping from a namespace and the NAT rule works. I tried to put veth5 into a namespace and ping internet, the rule works! However I don't want veth5 into a namespace and I cannot understand the reason why the rule works if veth5 is into a namespace. I'm using two VMs connected with each other, the first one has the configuration showed and the other one is my ISP server where I have configured a server PPPoE. The VM with the configuration showed doesn't have any other iptables rules and the routing rules are only those I need to forward traffic through the path described in the question
    – ica
    Jul 20, 2017 at 8:29
  • I'm confused now: I was simulating everything up to your veth6 in the namespace, not the source of the ping. veth5 really shouldn't have anything to do with it, and you certainly shouldn't have to put it into a namespace. What happens if you generate the ping from inside the namespace?
    – dirkt
    Jul 20, 2017 at 10:15
  • And while we are on the subject of veth5: It's part of the bridge, so why does it have an IP address? As a bridge port, it shouldn't; if anything, the bridge itself should have the address. Are you sure your bridge configuration is correct (output of bridge link)?
    – dirkt
    Jul 20, 2017 at 10:19
  • If I generate a ping from the namespace, masquerading works. My veth5 has an IP address because it is not a bridge port but it has a peer attached to the bridge.
    – ica
    Jul 20, 2017 at 10:31
  • So if it goes via veth5/br0/veth3 into the namespace, it doesn't work, but if you generate it directly in the namespace, it works? That's really odd. Is there a difference between those two cases if you capture the complete ping packet at veth6 or veth7? Masquerading happens after that, so if the packets are identical, I don't see how it can fail in one case and succeed in the other case ... Does it possibly already masq/nat the veth5/br0/veth3 ping packet before the final masq?
    – dirkt
    Jul 20, 2017 at 12:35

You must log in to answer this question.

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