Outbound packets are generated by host and has no packet mark but sure has connection's mark. So mark inbound packets, copy packet mark to connection mark, then mark new outbound packets back with connection's mark.
iptables -t mangle -A PREROUTING -i ipip0 -m conntrack --ctstate NEW -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m mark --mark 0x1 -j CONNMARK --save-mark
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
or shorter
iptables -t mangle -A PREROUTING -i ipip0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
and use fwmark selector in ip rule for policy based routing.
You should loose Strict Reverse Path checks for interfaces without default route
sysctl -w net.ipv4.conf.ipip0.rp_filter=2
RFC3704 Strict Reverse Path
For each inbound packet kernel checks "reverse path". Kernel swapps inbound packet's source and destination and check via what interface it will be routed in reverse direction by consulting routing table. In this check kernel doesn't respect packet's mark (fwmark).
With rp_filter=1, if the return interface for a packet does not match the interface through which the packet entered, the packet will be dropped.
For example, a host has two interfaces:
eth0 with 192.168.37.3 and
eth1 with 192.168.39.5.
The default route is via eth0.
default via 192.168.37.1 dev eth0 onlink
192.168.37.0/24 dev eth0 proto kernel scope link src 192.168.37.3
192.168.39.0/24 dev eth1 proto kernel scope link src 192.168.39.5
According to the routing table, the return path for a packet with src ip 8.8.8.8 entering through eth1 will be through eth0.
eth0 and eth1 are different interfaces and packet will be dropped at first routing decision, right after PREROUTING and before INPUT/FORWARD and never reach Local processes.
At the same time return path for a packet with src ip 192.168.39.45 entering through eth1 will be through eth1 so interfaces matched and packet's processing will continue.
