On Tue, Oct 23, 2012 at 6:28 PM, Mike <krustyar...
> Hi Michael,
> Thanks for the detailed reply. I've got the basic forwarding part
> down. The conceptual problem I'm having is how to have the server
> listen on one device (wlan0) but forward on another (tun0). Currently,
> if my VPN is active on the box with the ssh server, I can only ssh into
> the box through the VPN address, not directly to the IP my ISP gives
> me. This means that I'd be forwarding out through the same IP I'm
> coming from. Also, I currently use a dynamic dns provider to locate my
> box from afar; but this exposes the IP of my VPN unless the dyn-dns
> client is also bound to wlan0.
Your problem actually isn't a conceptual one, it's a technical
limitation. You can only have one "catch all" route, called your
default route (or gateway of last resort, or default gateway). When
your machine gets ready to send out a packet it first has to figure
out which interface it should go out onto, this is done by the routing
subsystem, using the FIB or routing table, you can view your routing
table by using netstat -rn (-r for routes -n for numeric, if you
forget the -n it tries to do DNS lookups for the network addresses and
this usually isn't what you want) ...
You'll get output similar to this (this is a simple example to start
with...the crafty/advanced among us will go why netstat and not route?
coz mortals can use netstat and it takes super user privs to use
$ netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
18.104.22.168 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 22.214.171.124 0.0.0.0 UG 0 0 0 eth0
Two entries, one, is our connected network.
So to send a packet out this table is consulted, most specific wins
(there's tiebreaker rules we'll ignore here)...if I'm trying to get to
126.96.36.199 the kernel matches the 0.0.0.0/0 entry, thats the default
route or gateway of last resort. Since nothing else matched it
forwards it onto whoever is listed there, in this case 188.8.131.52 (a
big Cisco router in this case since this is one of my colo boxes out
here in seattle). The packet is then sent over ethernet to the MAC
(ethernet) address of the Cisco there, who repeats the process, only
his routing tables are much, much, much more complete. In this
particular routers case it's actually at the core of the large ISP I
run, so it knows about basically every single route in the internet,
and which of it's connections can reach which addresses. It finds the
correct gateway, and then hands the packet off to that router...see
 for how these entries work...
So what happens when you bring up a VPN tunnel? The VPN tunnel client
does some magic for you. The first thing it does is it takes note of
that default gateway IP address, it'll need that in a moment. Once it
gets connected to the VPN server at the other end, it adds a very
specific route to your routing table, one that points the (outside) IP
of the VPN server at your default gateway, it then replaces your
default gateway with the tunnel (inside) IP address of the VPN server.
This has the effect of all un-tunnelled traffic without a more
specific route being directed towards the tunnel interface. The
tunnel interface encrypts it, wraps it into another IP packet and then
that packet which is encrypted and now is trying to go towards the
outside IP of the VPN server still goes to your ISP gateway device due
to the very specific route that your VPN client software has helpfully
So you can't really do what you want with the standard routing stack.
Even with a modified stack, if you're using a proxy, you're very
limited in what you can do since the connection will always look like
it comes from the local machine. Although maybe with the addition of
SELinux you can somehow mark packets/identify connections from the
sshd server side proxy so that iptables can see that...once you can
identify those packets you can get iptables to manipulate them, change
the next-hop (gateway) on them, or use a different FIB (forwarding
Information Base, thats what netstat -rn was showing us, the FIB, the
default FIB specifically).
I *have* done this using Juniper routers and security devices, but the
biggest single difference here is they're acting as a gateway, so they
can see traffic as coming from a specific host on a specific interface
and behave as instructed based on that information. The other
difference is I'm applying the policy to a host or a single network,
not individual flows. This lets you have say three different networks
attached to a single Juniper firewall and have networks A and B use
one default route while network C uses another (say A and B are office
and DMZ maybe, and C is the VoIP phones which need high priority).
This is conceptually similar to what you're doing.
 the route entries are in the form of network and netmask (my
netstat output says genmask)... the simplistic way of checking for a
match is to take the destination host, 184.108.40.206 and binary AND it
with the genmask. If what's left matches the network, you've a
winner! 204 & 255 = 204, 11 & 255 = 11, 247 & 255 = 247, 1 & 0 = 0
... 220.127.116.11 != 18.104.22.168 -- your Linux box doesn't actually do
this for every single packet they use a tree-like structure thats a
LOT faster, and then they cache the result of that lookup in a special
small table called the FIB cache so it's much much faster. Big Cisco
routers (just the high end ones moving many many gigabytes/second) do
it in hardware with specialty silicon because otherwise they can't
"Genius might be described as a supreme capacity for getting its possessors
into trouble of all kinds."
-- Samuel Butler