views:

1475

answers:

5

I have a java app (not running in any application container) which listens on a ServerSocket for connections. I would like it to only accept connections which come from localhost. Currently, after a connection is accepted, it checks the peer IP and rejects it if it is not the loopback address, but I know that peer IP addresses can be spoofed. So, if possible, I'd prefer to bind to a socket that only listens on the loopback interface; is this possible?

I've tried a few different things (such as specifying "127.0.0.1" as the local address when calling bind()) with no luck. Thanks in advance.

+4  A: 

Peer IP addresses cannot be spoofed in this manner, have you nothing to fear from using the technique of inspecting the peer and deciding to drop the connection during establishment.

However: binding to 127.0.0.1 should work, and cause the operating system to tell the connecting host that there is nothing listening if they connect on one of the systems other ip addresses. Can you amend this question with a compilable example? Perhaps you've made a simple error.

Jerub
A: 

When you bind your ServerSocket, specifying localhost should make the TCP/IP stack reject the connection. Even if this isn't working on your system, localhost can't (okay, maybe if someone hacked your TCP/IP stack and the default gateway router) be spoofed, since that address isn't routed through the physical interface.

I am curious as to why your binding doesn't succeed, what is your OS, Java version, etc?

Steve Moyer
+2  A: 

You could accept() the connection anyway then use getInetAddress() to ensure the address is an authorized one. If not, simply close() the socket straight away.

Or you could install your own security manager which will have its checkAccept() method called with the address and port of the remote site. Thet's much harder - I've never tried since the first solution has always been adequate for me.

paxdiablo
The original poster has already said that he's doing that, but doesn't want to because the remote side can be 'spoofed' or something.
Jerub
Jerub: The OP doesn't understand the spoofing. Pax: Any old security manager will do, you just need to set a policy giving the code the correct permissions (permission java.net.SocketPermission "127.0.0.1" "listen,accept", or something like that - need to catch the SecurityException from accept).
Tom Hawtin - tackline
A: 

If the peer address is spoofed, then there is nothing further that you can do.

However, to spoof 127.0.0.1 is not easy. You would have to have a TCP/IP stack dumb enough to accept such a packet. There would be no way of the spoofer receiving packets back. On a good TCP/IP stack, it should not be able to guess the sequence numbers so it can't keep up with the expected conversation.

Tom Hawtin - tackline
A: 

Thank you all for your help. I'm embarrassed to admit that this was all my mistake. Our application listens on two different ports, and I was binding one to the loopback interface but testing against the other. When I actually try to telnet to the correct port, everything works fine (i.e., binding to "127.0.0.1" does exactly what it's supposed to).

As for spoofing the loopback address, you guys are right. I shouldn't have made it sound like the primary concern. Really, the desired behavior is to only take local connections, and binding to only the local interface is a more direct way of achieving that than accepting all connections and then closing non-local ones.