No need for virtual interfaces here. What you want is multiple IP address on the same device, and good routing tables with policy routing to select which routing table to use. Now, on the configuration part. Let's configure your ip addresses with a /32, so we can create our on-link routes ourselves
ip addr flush dev eth0
ip addr add 192.168.1.yourhost/32 dev eth0
ip addr add 192.168.2.yourhost/32 dev eth0
ip addr add 192.168.3.yourhost/32 dev eth0
Now for the routing table. The first routing table will match packets that go to your lans.
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.yourhost table 2
ip route add 192.168.2.0/24 dev eth0 src 192.168.1.yourhost table 2
ip route add 192.168.3.0/24 dev eth0 src 192.168.1.yourhost table 2
table 2 specifies which routing table to use. 2 is an arbitrary number. numbers can be mapped to names by editing /etc/iproute2/rt_tables. Let's add 2 lan to that file, now you can simply use table lan.
Now, let's use that routing table by default :
ip rule add table lan
Now, if you look at the output of ip rule, you will see something like this :
0: from all lookup local
99: from all lookup lan
32766: from all lookup main
32767: from all lookup default
local is a reserved table used so the kernel can check if an ip address is his own IP address, lan is our table, main is the usual routing table that you know, and default is a special table for packets that we can't route. Basically, the kernel will try these rules by starting from the first, and, if it can't find a route in that table, it goes to the next rule.
So we added another routing table where we put our routes to the LAN, which is tryed before the main table. Now let's add a default route in main: When you don't bind a socket to a IP address, you will only use this default route. Let's choose 192.168.1.1:
ip route add default via 192.168.1.1 src 192.168.1.yourhost
Now, if you bind your socket to 192.168.2.yourhost, you don't want to use that default route, but another. Let's add this default route to another routing table:
ip route add default via 192.168.2.1 src 192.168.2.yourhost dev eth0 table 3
# and while we are at it, let's do this for 192.168.3.1 as well
ip route add default via 192.168.3.1 src 192.168.3.yourhost dev eth0 table 4
Now you want to use these routing table, but only if your socket is bound to these other IP addresses.
ip rule add from 192.168.2.yourhost iif lo table 3
ip rule add from 192.168.3.yourhost iif lo table 4
from 192.168.2.yourhost will make the kernel only try the table if the IP source address in the packet is 192.168.2.yourhost. iif allows to specify from which interface the packet was received (which is useful when you forward traffic) with a special exception, where iif lo means that the traffic was generated locally.
Now you can check if it works by trying or by using ip route get commands to test your routing tables :
$ ip route get 192.168.2.5
192.168.2.5 dev eth0 src 192.168.2.yourhost
cache
$ ip route get 64.34.119.12
64.34.119.12 via 192.168.1.1 dev eth0 src 192.168.1.yourhost
cache
$ ip route get 64.34.119.12 from 192.168.2.yourhost
64.34.119.12 via 192.168.2.1 dev eth0 src 192.168.2.yourhost
cache