Antony Lesuisse
2003-Dec-12 02:15 UTC
How to bypass the local routing table, to simulate a hub
Imagine, on a linux box, having 3 different network interfaces on the same switch. It is for simulating a network, using virtual tun/tap interface: ----------------+-----+------------------------ Hub simulator|Linux| Userspaces apps | | ?--|-----|--- tap0 192.168.1.1 ? | | /dev/net/tun ?--|-----|--- tap1 192.168.1.2 ? | | ?--|-----|--- tap2 192.168.1.3 | | ----------------+-----+----------------------- How can you tell the linux networking stack that a packet for 192.168.1.2 has to be sent via the network interface tap0 or tap2 (according to the sin_addr) to the WIRE and be received by tap1? I would like that, for packets that comes from process, the kernel doesn''t recognize the dest ip as local so that the packet will be sent over the interface even if there is an other interface configurated with the destination ip on the same kernel. For example i will configure a HTTP server on tap2 binding 192.168.1.3:80 and i will launch an HTTP client binding IP 192.168.1.1 trying to make TCP connection to 192.168.1.3:80 doing a GET. Everything on the same computer. My hub simulator will sometimes simulate packet loss. ping -I tap0 192.168.1.2 should go trought my simulator and not use lo. ping 192.168.1.2 should go trought my simulator (ie using 192.168.1.1) as source Acoording to my understanting of the linux network stack the problem is that there is no way to skip the lookup in the local routing table: You cannot change the 0: of ip rules ip rule: 0: from all lookup local 32766: from all lookup main 32767: from all lookup default ip route show table local: local 192.168.1.1 dev eth0 proto kernel scope host src 192.168.1.1 local 192.168.1.2 dev eth0 proto kernel scope host src 192.168.1.2 local 192.168.1.3 dev eth0 proto kernel scope host src 192.168.1.3 ... Somebody on irc told me to do something like this: iptables -A PREROUTING -t mangle -p tcp -s MYIP1 -j MARK --set-mark 10 iptables -A PREROUTING -t mangle -p tcp -s MYIP2 -j MARK --set-mark 20 ip rule add fwmark 10 table first ip rule add from MYIP1 to 0.0.0.0/0 lookup second ip route add default via eth2 table second But it doesn''t change the fact that linux still lookup the local routing table. TIA Antony Lesuisse BONUS: Here is my small (but fully functionnal) network hub simulator in python: #!/usr/bin/python2.2 # hub with a probabilty of 0.9 import fcntl,math,os,random,select,sys,time # TUN TAP kernel interface def net_alloc(name=""): s = len(name) if s>15: raise "name too long" fd = os.open("/dev/net/tun",os.O_RDWR) print fd if fd == -1: raise "could not open /dev/net/tun" ioctl_int = 0x400454ca ioctl_ifreq = name+(16-s)*''\x00''+''\x02''+15*''\x00'' name = fcntl.ioctl(fd,ioctl_int,ioctl_ifreq) name = name[:name.find(''\x00'')] return (fd,name) # Contruction of a hub hub = [] hubname = {} for i in range(2): fd,name = net_alloc() hub.append(fd) hubname[fd]={''fd'':fd, ''name'':name} os.system("ifconfig -a") os.system("ifconfig tap0 192.168.66.1; ifconfig tap1 192.168.66.2") # hub simulation while 1: (fdin,a,b) = select.select(hub,[],[],1.0) print "event:",fdin for i in fdin: frame = os.read(i,2048) print "%s:frame:%s"%(hubname[i][''name''],repr(frame)) for j in hub: if j != i: if random.random() < 0.9: os.write(j,frame) else: print "lost:%s:to:%s"%(hubname[i][''name''],hubname[j][''name'']) -- Antony Lesuisse GPG EA2CCD66: 4B7F 6061 3DF5 F07A ACFF F127 6487 54F7 EA2C CD66 _______________________________________________ LARTC mailing list / LARTC@mailman.ds9a.nl http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
Darryl Miles
2003-Dec-12 15:09 UTC
Re: How to bypass the local routing table, to simulate a hub
Antony, I have not completely read / understood your situation, so forgive me for jumping in. I don''t know much about tap0 device so maybe you can eligthen me. But from what I can see you can setup a NETWORK on a tapX interface and the kernel will route all traffic to the interface as-if its a hardware device, except its not, its a software device that passes packets between userspace and the kernel interface through the use of a file descriptor / socket, created by opening a device like file. I use the word NETWORK since it behaves like a normal interface, that is you give it an IP address that represents the kernels interface facing the userspace software/virtual network. Therefore you should have setup the interface with a netmask to allow other IPs to exist on that network, it is those IPs that your application program should assume and use. To do this means the tap0 interface is configured along the lines of 192.168.1.8/30, using a netmask of 255.255.255.252, using 192.168.1.9 as the kernel interface IP, 192.168.1.10 as your applications IP. Then run your "ping -I tap0" again. Now if on the other hand you are wanting to sniff all traffic to a particular IP address from your ethernet segment, but not have the kernel stack treat the packets as local, then down all the tapX interfaces, then checkout AF_RAW, NETLINK, whatever the current scheme is for injecting / sniffing packets and setup a proxy ARP addresses of the IPs you want to assume on the LAN. However if the box this is all hosted on has a lot of other traffic destined for the kernel stack you will have to receive, filter, discard all those packets through into userspace. Maybe socket filters can help in the kernel, but the point is the tapX interfaces when used as a NETWORK would be a better solution. Darryl Antony Lesuisse wrote:>Imagine, on a linux box, having 3 different network interfaces on the >same switch. It is for simulating a network, using virtual tun/tap >interface: > > >----------------+-----+------------------------ >Hub simulator|Linux| Userspaces apps > | | > ?--|-----|--- tap0 192.168.1.1 > ? | | >/dev/net/tun ?--|-----|--- tap1 192.168.1.2 > ? | | > ?--|-----|--- tap2 192.168.1.3 > | | >----------------+-----+----------------------- >_______________________________________________ LARTC mailing list / LARTC@mailman.ds9a.nl http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
Antony Lesuisse
2003-Dec-12 15:18 UTC
simpler version, How to bypass the local routing table?
imagine the folowing simpler configuration Hub | Linux +----- eth0 192.168.1.1/24 | | +----- eth1 192.168.1.2/24 | I would like that the packets of ping -I eth0 192.168.1.2, go on wire via the eth0 interface to the hub, that the hub broadcast them to eth1, and the kernel receive them from eth1 and process it and the send the ICMP replies back to the wire via eth1, and eth0 and ping recieve it. For that the kernel HAS to NOT recognize the dest ip (192.168.1.2) as local, when packets comes from processes, so that the packet will be sent over the interface even if there is an other interface eth2 configurated with the destination ip (192.168.1.2) on the same kernel. So the problem is how to bypass the lookup in the table shown by: ip route show table local Or how to change the priority of the rule 0: shown by: ip rule One dirty solution might be altering the dest ip of outgoingpackets that comes from processes (OUTPUT ROUTING), using ip&(1<<8), to fool the kernel. Then having the HUB (i can program the hub) to remove that bit. (but that forbids using with that bit set). References: Guide to IP Layer Network Administration http://linux-ip.net/ Kernel Packet Traveling Diagram http://www.docum.org/stef.coene/qos/kptd/ -- Antony Lesuisse http://antony.lesuisse.com GPG EA2CCD66: 4B7F 6061 3DF5 F07A ACFF F127 6487 54F7 EA2C CD66 _______________________________________________ LARTC mailing list / LARTC@mailman.ds9a.nl http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
Darryl Miles
2003-Dec-12 16:24 UTC
Re: simpler version, How to bypass the local routing table?
From your previous example my understanding of the hub, was that it was on a tapX interface in software on the same box, not another physical host on the ethernet segment. I see, your immediate problem is the packets won''t leave the host and don''t appear appear on the wire, the only (proper) way around this is not to use the real IP of the other ethernet interface as the dest address during the ping. Instead create a fake IP to use. Then perform address translation at the hub, which is neither of the 1.1 or 1.2 addresses itself, but say 1.3, that translates all packets going to the fake addresses in each direction, don''t forget you have to translate both the src and dest addresses to each others fake address, replace fake with real and real with fake. The fake addresses would also best be in another 2 subnet of their own, call them 192.168.3.1/24 and 192.168.4.2/24. I''d also recommend you don''t overlap the subnets of eth0 and eth1 on the same box, make eth1 192.168.2.2/24 or something. Mangling the IP on OUTPUT won''t work, AFAIK, since it never gets into that routing path out of the kernel as its in the local table. But your original request is improper from a network standpoint, each host has one IP stack, trying to split it in the middle is asking for trouble. Antony Lesuisse wrote:>imagine the folowing simpler configuration > >Hub | Linux > +----- eth0 192.168.1.1/24 > | | > +----- eth1 192.168.1.2/24 > | > > >_______________________________________________ LARTC mailing list / LARTC@mailman.ds9a.nl http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
Julian Anastasov
2003-Dec-12 16:41 UTC
Re: simpler version, How to bypass the local routing table?
Hello, On Fri, 12 Dec 2003, Antony Lesuisse wrote:> So the problem is how to bypass the lookup in the table shown by: > ip route show table localhttp://www.ssi.bg/~ja/#loop Regards -- Julian Anastasov <ja@ssi.bg> _______________________________________________ LARTC mailing list / LARTC@mailman.ds9a.nl http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/