I figured out the main problem: (local process) -> (routing decision) -> [raw:output] -> contrack -> [mangle:output] -> (reroute check) -> [nat:output] -> [filter:output] -> ...
When the local process generates a packet, the network stack takes the routing decision really early on. In our case earlier then we are able to mark with iptables the packets. That happens in the mangle table and therefore the policy routing table is not considered at this point. My naive assumption was that the reroute check would be done unconditionally. Unfortunately, this is not true. The reroute check is only done if the packet was modified in the mangle output chain. So for example if you look at a simple ping the code path relevant to route is: net/ipv4/ping.c: ping_v4_sendmsg() ip_route_output_flow() net/ipv4/netfilter/iptable_mangle.c ipt_mangle_out() ip_route_me_harder() ip_route_output_key() ip_route_output_flow() That means the NAT rule is necessary, e.g. iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.1.100 The policy routing table is not completely useless. For example the process could mark its packet on its own. Another possible way is to have a cgroup controller setting the SO_MARK or we teach the policy routing table to match on sk_classid (cls cgroup controller). Back to original problem. I am preparing a patch for adding the missing NAT rules which should fix this problem. Obviously, we don't need both the policy routing table and the NAT rules. But I am reluctant to rip out the policy routing code at this point. Maybe someone is using it already. cheers, daniel _______________________________________________ connman mailing list connman@connman.net https://lists.connman.net/mailman/listinfo/connman