<div dir="ltr">Hi list,<div><br></div><div>I am wondering if it is possible to create ~1000 of tunnels from a single linux machine for testing purposes and route the traffic based on UID of the processes. I was trying to do PoC with just two tunnels  using the following setup:</div><div><br></div><div>strongswan-5.5.3, kernel 4.12.5-gentoo<br></div><div><br></div><div><div>hotgeorge horky # cat /etc/ipsec.conf</div><div>conn node13</div><div>  auto=add</div><div>  type=tunnel</div><div>  keyexchange=ikev2</div><div>  ike=aes256-sha1-modp1024!</div><div>  esp=aes256-sha1-noesn!</div><div>  left=%defaultroute</div><div>  leftid="SomeID"<br></div><div>  leftsourceip=%config4</div><div>  right=node13</div><div>  rightid=myrightid</div><div>  rightsubnet=<a href="http://0.0.0.0/0">0.0.0.0/0</a></div><div>  authby=psk</div><div>  mark_out=13</div><div>  leftupdown=/usr/bin/sudo -E /etc/ipsec_mark_updown</div><div><br></div><div>conn node14</div><div>  auto=add</div><div>  type=tunnel</div><div>  keyexchange=ikev2</div><div>  ike=aes256-sha1-modp1024!</div><div>  esp=aes256-sha1-noesn!</div><div>  left=%defaultroute</div><div>  leftid="SomeID"<br></div><div>  leftsourceip=%config4</div><div>  right=node14</div><div>  rightid=myrightid</div><div>  rightsubnet=<a href="http://0.0.0.0/0">0.0.0.0/0</a></div><div>  authby=psk</div><div>  mark_out=14</div><div>  leftupdown=/usr/bin/sudo -E /etc/ipsec_mark_updown<br><br>I have set charon.install_routes = 0 to avoid installing default route to route table 220, so I can actually setup the second tunnel.<br><br>I use following static iptables rules to mark the traffic based on UID:</div></div><div><div>iptables -t mangle -A OUTPUT -m owner --uid 1013 -j MARK --set-xmark 0xd/0xffffffff</div><div>iptables -t mangle -A OUTPUT -m owner --uid 1014 -j MARK --set-xmark 0xe/0xffffffff</div></div><div><br></div><div>The interesting content of /etc/ipsec_mark_updown script is the following:</div><div><div>MY_DEFAULT_GW=10.7.65.1</div><div>case $PLUTO_CONNECTION in</div><div>  *node13*)</div><div>  <span style="white-space:pre">    </span>MARK=13</div><div><span style="white-space:pre">       </span>;;</div><div>  *node14*)</div><div>  <span style="white-space:pre">      </span>MARK=14</div><div><span style="white-space:pre">       </span>;;</div><div>esac<br><br></div></div><div><div>ROUTE_TABLE=$((1000+MARK))</div><div><br></div><div>case $PLUTO_VERB in</div><div>  up-client) <span style="white-space:pre">    </span></div><div><span style="white-space:pre">      </span>ip route flush table $ROUTE_TABLE<br></div><div><span style="white-space:pre">   </span>ip rule del fwmark $MARK table $ROUTE_TABLE 2>/dev/null</div><div><span style="white-space:pre">    </span>ip rule add priority 10 fwmark $MARK table $ROUTE_TABLE</div><div><span style="white-space:pre">       </span>ip route add default via $MY_DEFAULT_GW proto static src $PLUTO_MY_SOURCEIP table $ROUTE_TABLE<br>        ;;</div></div><div><br></div><div>Now, if I fire up the two tunnels:</div><div>ipsec up node13<br>ipsec up node14<br><br></div><div>I have the following routing rules:<br><div>hotgeorge horky # ip rule list</div><div>0:<span style="white-space:pre">        </span>from all lookup local </div><div>10:<span style="white-space:pre">    </span>from all fwmark 0xd lookup 1013 </div><div>10:<span style="white-space:pre">  </span>from all fwmark 0xe lookup 1014 </div><div>220:<span style="white-space:pre"> </span>from all lookup 220 </div><div>32766:<span style="white-space:pre">   </span>from all lookup main </div><div>32767:<span style="white-space:pre">  </span>from all lookup default </div></div><div><br></div><div>And following routing table:</div><div><div>hotgeorge horky # ip route list table 1013</div><div>default via 10.7.65.1 dev wlo1  proto static  src 100.111.0.91 </div><div>hotgeorge horky # ip route list table 1014</div><div>default via 10.7.65.1 dev wlo1  proto static  src 100.111.0.167 </div><div>hotgeorge horky # ip route list table 220</div></div><div><br></div><div>Where table 220 is empty.</div><div><br></div><div>The trouble is the if I execute curl under user test_1013 (with uid 1013), it times out on sending a DNS query:</div><div>su test_1013 -c "curl <a href="http://ip-info.ff.avast.com/v1/info">http://ip-info.ff.avast.com/v1/info</a>"<br></div><div><br></div><div>When I manually specify the source address, it works:</div><div><br></div><div><div>su test_1013 -c "curl <a href="http://ipv4bot.whatismyipaddress.com">http://ipv4bot.whatismyipaddress.com</a> --interface 100.111.0.91 --dns-ipv4-addr 100.111.0.91"; echo</div><div>77.234.40.153</div></div><div><br></div><div><div>su test_1014 -c "curl <a href="http://ipv4bot.whatismyipaddress.com">http://ipv4bot.whatismyipaddress.com</a> --interface 100.111.0.167 --dns-ipv4-addr 100.111.0.167"; echo</div><div>77.234.40.182</div></div><div><br></div><div>So it seems that the kernel's source address selection does not work correctly in my case. I am able to workaround my troubles by specifying SNAT rules like:</div><div><br></div><div>iptables -t nat -A POSTROUTING -m mark --mark $MARK ! -s $PLUTO_MY_SOURCEIP -j SNAT --to-source $PLUTO_MY_SOURCEIP<br></div><div><br></div><div>But I would like to avoid doing that.</div><div><br></div><div>Could you please enlighten me what I am doing wrong? It seems that if I let strongwan install the routes to the table 220 (without any restrictions to marks), the source address is selected correctly. This got me thinking that the source ip selection probably happens sooner than marking the packets. So I tried  to insert my marking rules based on uid to OUTPUT chain of raw table. When I did this, it did not help and moreover, even the case with manual selection of source ip in curl stopped working.<br><br></div><div>I would be grateful for any tips.</div><div><br></div><div>Note: I know that using network namespaces could sound like a better idea than this. Unfortunatelly, even the newest kernel contain some race conditions when destroying namespaces rapidly preventing us to use this way.</div><div><br></div><div>Thanks</div><div>Jiri Horky</div></div>