Showing posts with label arp. Show all posts
Showing posts with label arp. Show all posts

Thursday, March 21, 2013

Detecting hosts that cross connect two networks...

There are different scenarios in which you can have a situation where some of your clients are connected in the same time to two different networks of different trust levels. This is dangerous because effectively they can be used as a staging point for potential attackers or malware to "jump" from less trusted network to more trusted one.

For example, suppose that you have protected internal wired LAN, and in the same time you have wireless LAN that is used for guests and allowed unrestricted access to the Internet, as shown in the figure below. Someone, from your internal and protected network, might intentionally or accidentally connect to the wireless network too, and in that case he/she will shortcut the two networks. If you thought that you can use MAC addresses to detect such hosts, you can not, for a simple reason that in one network host is connected using wired ethernet card with one MAC address, and in the second network it is connected using WLAN network card with another MAC address.

Hypothetical situation to illustrate how internal host might shortcut two networks of different trust levels
So, how to detect those hosts that shortcut two networks? Actually, there is an easy and elegant way. Namely, you can send ARP requests on one network for IP addresses on another network. ARP module, by default, doesn't know or care for routing tables so that it knows on which interface it should respond with specific addresses. If we look again on the figure above, this means that you can run the following command from the proxy host (the host above firewall):
arping -I eth1 10.0.0.250
I assume in that command that eth1 is the interface connected to AP. What will happen is that broadcast will be sent on the wireless network and the client will respond with its wireless MAC address even though that address is not used on the wireless network.

So, I hope the idea is clear now. To detect if there is some host cross connecting two networks I send arp request on a host (i.e. proxy host) for each possible IP address used on the the other network (i.e. local protected network in the figure above).

Note that it is possible to disable such behavior on Linux machines using sysctl variable /proc/sys/net/ipv4/conf/*/arp_filter. You can find more information, for example, here.

nmap games

Now, there is another problem. How to scan the whole network without manually trying each possible IP address. The first solution is, obviously, to use nmap. Nmap is a great tool for network scanning, but in this case it has a problem, I tried to run it in the following way, but unsuccessfuly:
# nmap -PR -Pn -e eth1 10.0.0.0/24
Starting Nmap 5.51 ( http://nmap.org ) at 2013-03-21 10:07 CET
nexthost: failed to determine route to 10.0.0.0
QUITTING!
Option -PR requires ARP scan, -Pn disables ping scan, and -e eth1 tells nmap to send packets via interface eth1. The problem is that I'm trying to scan network 10.0.0.0/24 on interface eth1 and there is no route in routig tables that tells kernel/nmap that network is really connected on interface eth1. So, nmap refuses to scan those addresses. One solution is to temporarily add that route:
ip route add 10.0.0.0/24 dev eth1
But this isn't an option if the route already exists in order for the hosts on the protected network to be able to access proxy, i.e. if there is route similar to the following one:
# ip ro sh
...
10.0.0.0/24 via 172.16.1.1 dev eth0
...
Again, I'm making a lot of assumptions here (network between proxy and firewall, IP addresses and interfaces) but I hope you understand the point. The given route is in the routing tables and removing it isn't an option.

Next try was using -sn switch, i.e. to disable port scan:
# nmap -PR -Pn -sn -e eth1 10.0.0.0/24
Starting Nmap 5.51 ( http://nmap.org ) at 2013-03-21 10:07 CET
Well, now nmap worked, sort of, because it showed all the hosts are up. Using tcpdump I found that it didn't send anything to the network. Reason: it thinks this is remote network, pings are disabled, arp cannot be used, and finally, because of -Pn, assumes all the hosts are up. So, I was again at the beginning.

Simple arping solution

Until I figure out how to force nmap to send arp probes without worrying  about routing tables here is a simple solution using arping command:
#!/bin/bash

TIMEOUT=4

for i in {1..254}
do
if arping -q -f -w \$TIMEOUT -I eth2 10.0.0.\$i
then
echo "10.0.0.$i is up"
fi
done
There are three problems with this solution:
  1. In case your network has netmask other than /24 you'll have to change this script, i.e. it is a bit more complicated. How much, depends on the network mask.
  2. The problem with this solution is that it is slow. For example, to scan 254 addresses and with timeout of 4 seconds, it will take about 17 minutes to scan the whole address range assuming no address is alive (what is actually desired state on the network).
  3. Finally, timeout value is a bit tricky to determine. Majority of the responses are really quick, i.e. under a second. But some devices respond slower, i.e. when they entered some kind of a sleep state.
Still, it is a satisfactory solution until I find a way to use nmap for that purpose. If you know how, please, leave a comment.

Tuesday, November 22, 2011

SSH TAP tunnels: Using routing instead of bridging...

In the previous post about SSH tunneling, I used bridging functionality within Linux kernel in order to connect remote network with local laptop. But it is also possible to use routing in that case. The reason why you would prefer routing, instead of bridging, is the quantity of traffic that might be flowing from the remote network to your interface. And because you are probably connected with slower link than available bandwidth on the local network itself, that could be a real problem. So, routing could help in this case. Note that you are loosing ability to use some protocols, most notably those that use broadcasting since routing code won't route those packets.

The idea is to use routing in combination with proxy ARP. Basically, everything stays the same except you are not using bridging and you need to setup some basic forwarding features on remote host. So, here we go.

First add an explicit route for your remote host. That way it won't happen that you can not access it because the local network on which remote host is will be accessed in a special way:
ip route add remote_host via default_current_router
In case you don't know IP address of your default router (default_current_router) you can find it out using ip route sh command. And for remote_host you need to use IP address with network mask 32!

Now, log in to remote host using the usual ssh command that creates tap tunnel (for the meaning of parameters and what happens see previous post):
ssh -C -w any -o Tunnel=ethernet root@remotehost
After logging in, on local host add IP address from remote network that you are assigned when you directly connect on the remote network. In our example network this is the address 192.168.0.40/24 (see this previous post).

Now we have one interesting situation which I'm going to describe in some detail.

Start arping command on remote host like this (read this post about arping command):
arping -I tap0 192.168.0.40
Basically, you won't receive response. If you start tcpdump command, you'll notice that ARP requests are arriving, but there are no responses. The reason why there are no responses is because your local machine sees unexpected address in request and so ignores it.

You can turn on logging to see that those are really ignored with this command:
echo 1 > /proc/sys/net/ipv4/conf/tap0/log_martians
and now look into log file (/var/log/messages). You'll notice messages similar to the following ones:
Nov 22 14:37:25 w510 kernel: [147552.433215] martian source a.b.c.d from e.f.g.h, on dev tap0
Nov 22 14:37:25 w510 kernel: [147552.433221] ll header: ff:ff:ff:ff:ff:ff:16:90:4a:17:9d:d1:08:06
As you can see, it's called martian address. :)

Now, you can two options. The first one is to turn off filtering and the second one is to assign IP address to tap0 interface on remote host too. In general I don't suggest that you turn off rp filtering, but since in this case we are turning it off on a special (and restricted) interface I'll go that route, and also to save one IP address. So, on local machine do the following:
echo 1 > /proc/sys/net/ipv4/conf/tap0/rp_filtering
If you now try arping from local machine to remote machine, trying to reach IP address of remote machine, it won't work! You have to turn off rp filtering on remote machine too. So, execute the previous command there also.

One more thing for L2 part to fully work. When local machine asks from some address on local network, via tun0, remote host has to announce itself. For this purpose Proxy ARP is used but it has to be turned on. So, turn it on with the following command:
echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp
If you now try to "arping" any IP address, you'll aways get MAC address of tap0 on remote machine, and that's exactly what we wanted. But, you also need to do that because when machines on remote network search for you, then remote host has to announce himself and relay/forward everything over the tunnel to you.
echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
I'm assuming that the interface name which attaches remote host to local network is named eth0, and I'm also assuming that you didn't create bridge device and attached eth0 to it (as it was described in the previous post).

Ok, time for L3 part. Everything has to be done on a remote machine. So, on a remote machine, first tell it that 192.168.0.40 is attached to tap0 interface:

ip route add 192.168.0.40/32 dev tap0
Next, allow IP forwarding:
echo 1 > /proc/sys/net/ipv4/ip_forward
And that's it. Only what's left is to automate the whole procedure.

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)

Blog Archive