5
votes

Please don't criticise the solution. It's not my design and yes, it sucks.

On a computer running Linux, and using C, we need to verify that a TCP connection made to a process is from the same machine. Doing it by IP address is problematic since the OS is generating two IP addresses and the process only knows one. Anyway, verifying by IP address is a bit poor.

We want to do the verification by comparing the "remote" MAC address to the local MAC address. We already get the local MAC address. All I need to know is how to get the "remote" MAC address. It's in the packet that gets sent when forming the connection (and in all subsequent ones too). How do we drag it out of the ethernet layer?

Before anyone says this again, I KNOW you cannot get the MAC address of the remote host if it's not on the same subnet/LAN. That's fine. Presumably we'll get something like 00:00:00:00:00:00 and since that is different to the local MAC address it will be different - just what we want.

--

So, to summarise, we have a TCP connection socket fd, we've received a data packet, how do we then find the MAC address of the remote host, the MAC address that was in the packet's header?

4
Are you trying to determine identity? because I can think of several better ways to do so than by using a spoofable MAC address - Hasturkun
If the local packets are coming in with two different IP addresses, how do you know they're not going to come in with two different MAC addresses? If some packets are coming through the loopback adapter, they don't go anywhere near the hardware and so won't have a MAC address at all (IIRC). - Ernest Friedman-Hill
Are you aware of the fact that it's possible to bind the server to the loopback interface only? In that case only clients on the same machine can make a connection (and they must use 127.0.0.1 as remote address), it is not possible to connect from another machine. - Bart
Of course you said this isn't your design, but make sure everyone is aware that if this is for security reasons, then it's not really doing much. It's easy to change MAC addresses at will. - Michael Mior
Hasturkun: Yes I know which is why I said "First of all, please don't criticise the solution. It's not my design and yes, it sucks". Mr Mior: I know. I'm no expert but I think we might be safer on the grounds that the SYN/ACK response to someone spoofing the MAC address shouldn't go anywhere near the spoofer - but like I say I'm not an expert. And I will be doing what I can to raise awareness, but I doubt it will have much effect. Bart: Good idea. I'll suggest it and see what happens. - AlastairG

4 Answers

11
votes

If I understand correctly, you are not trying to tell remote machines apart, but to use the idea that the source and destination MAC would match on traffic sent from a machine to itself in order to allow only local traffic.

This seems rather roundabout, and has been pointed out, insecure.

A somewhat better idea might be to have the TCP client listen only on the loopback interface (127.0.0.1) and not on INADDR_ANY. Or go a step further and use a unix-domain socket instead of a TCP one (a common method used by X servers today to prevent the possibility of remote connections)

3
votes

The MAC address of a live same-subnet TCP connection will almost certainly be in the ARP cache.

On Linux, you could examine the ARP cache by looking in /proc/net/arp. Here is what it looks like on my Ubuntu box:

aix@aix:~$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
10.0.0.32        0x1         0x2         00:1e:4f:f5:be:dc     *        eth0
10.10.10.1       0x1         0x2         00:1f:6c:3e:02:e3     *        eth0

There's probably some callable API that you could use to get to the same data if you're averse to parsing the pseudo-file.

0
votes

How about configuring a firewall (internal or external) to block or MAC-filter external traffic on the port in question?

0
votes

A loopback connection (whether it's over the loopback interface or some other interface) it not routed over any ethernet device and therefore does not have a MAC address associated with it.

I suggest you just use getsockname and getpeername to get the local and remote IP address and compare that they are equal. That will work without any a priori knowledge of the configured IP addresses of your system.

Further, if you want to be IPv4/v6 agnostic, you could use getnameinfo with the NI_NUMERIC flag to convert both addresses to numeric string representations and strcmp them.