3

I would like to make a certain user have a specific source IP address. For this purpose, I added a secondary IP address to the network interface and tried to enforce the source IP using ip6tables and policy routing. Summary:

  • All IPv6-traffic gets routed via a IPv4 OpenVPN interface (tap0), the gateway is 2001:db8::1.
  • If the user is someuser, the source address must be 2001:db8::3
  • Otherwise, the source address is 2001:db8::2.

The default routes and addresses are set up as follows:

ip -6 addr add 2001:db8::2/112 dev tap0
ip -6 route add default via 2001:db8::1 src 2001:db8::2 dev tap0

For the someuser router, I mark all outgoing packets and attempt to route those packets with a different source address by using a separate routing table. These are set up with:

ip6tables -t mangle -A OUTPUT -m owner --uid-owner someuser -j MARK --set-mark 123
ip -6 rule add fwmark 123 table 1002
ip -6 addr add 2001:db8::3/112 dev tap0
ip -6 route add default via 2001:db8::1 src 2001:db8::3 dev tap0 table 1002

For some reason, all traffic still have the 2001:db8::2 source address. I can see that the ip6tables rule is hit, but the source IP is still wrong. Verified with NFLOG target + Wireshark and with curl ip.appspot.com.

Any ideas what I did wrong?

Lekensteyn
  • 6,111
  • 6
  • 37
  • 55
  • Try to add `set-mark` rule to the `filter` table instead of `mangle` – Glueon Oct 15 '14 at 12:31
  • @Glueon That makes no difference as I expected. The filter table is visited slightly later than the mangle table for OUTPUT. See [this picture of the packet flow](https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg). – Lekensteyn Oct 15 '14 at 12:34
  • Before any packets are sent, the routing table is consulted to find the outgoing interface. This is done in order to identify the default source address to be used. However since no packet has been produced yet, your firewall rule has no effect at this stage. The choice made through the routing table is only used if the application doesn't specify another address explicitly. The application can use the `bind` system call to chose an address - even one assigned to a different interface. – kasperd Oct 19 '14 at 11:18

1 Answers1

2

Edit: misunderstood your post at first, rewrote the answer.

When you do routing you don't change packet content, you just choose the right interface to foward it to. So this won't change the source IP address you got. It will go to the right routing table and the right interface but that's all. To do this you need NAT.

So you need to masquerade in POSTROUTING, for instance with :

/sbin/ip6tables -A POSTROUTING -t nat -m mark --mark 123 -j SNAT --to-source 2001:db8::3
Xavier Lucas
  • 12,815
  • 2
  • 44
  • 50
  • This is exactly what I am using now since it does not seem to be possible to rewrite the src addr using policy routing. It somehow makes sense, the "reroute check" in [the packet flow](https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg) probably only looks at which interface a packet should be delivered. The source address is likely filled in when a socket is opened and connected. – Lekensteyn Oct 15 '14 at 16:57
  • @Lekensteyn Exactly. – Xavier Lucas Oct 15 '14 at 16:59
  • I'd call this a workaround rather than a solution. Unfortunately I don't know whether a real solution exists. – kasperd Oct 19 '14 at 11:12
  • @kasperd That's not a workaround, that's how routing works. – Xavier Lucas Oct 19 '14 at 11:43
  • NAT always has been and always will be a workaround. – kasperd Oct 19 '14 at 12:30
  • @kasperd What are you trying to achieve with your comments here ? Post your own solution. – Xavier Lucas Oct 19 '14 at 12:45
  • I didn't say a solution exists. Usually workarounds are used when you don't have a solution. A solution could be one of: `1.` Have applications explicitly bind to the desired IP address. `2.` Run applications that need another source IP address in a different network namespace. `3.` Update the source address selection code to include user ID as a criteria in the decision. – kasperd Oct 19 '14 at 13:10
  • @kasperd The question as I read it is systemwide for a specific user so what you are speaking about is not possible. The end. – Xavier Lucas Oct 19 '14 at 13:30
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/17997/discussion-between-kasperd-and-xavier-lucas). – kasperd Oct 19 '14 at 13:46