8

I have a SocketServer accepting incoming connections. For security reasons I should only allow local connections (connections from the machine on which server is running).

How can I determine if an incoming connection is from another machine? Is the following code safe for this?

Socket socket = someServerSocket.accept();
String remoteAddress = socket .getInetAddress().getHostAddress();
if (!fromThisMachine(remoteAddress)) {
    // Not from this machine.
}

while fromThisMachine() method is like this:

public boolean fromThisMachine(String remoteAddress) {
    try {
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress inetAddress = addresses.nextElement();
                String hostName = inetAddress.getHostName();
                String hostAddr = inetAddress.getHostAddress();
                if (hostName.equals(remoteAddress) || hostAddr.equals(remoteAddress)) {
                    return true;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    log("Unauthorized request to server from: " + remoteAddress);
    return false;
}

Thanks, Mohsen

Mohsen
  • 3,512
  • 3
  • 38
  • 66

3 Answers3

11

InetAddress.getByName( null ) always returns the loopback address. See the javadoc

    int port = .....
    SocketAddress socketAddress =
        new InetSocketAddress( InetAddress.getByName( null ), port);
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(socketAddress);
    serverSocket.accept();
Alexander Pogrebnyak
  • 44,836
  • 10
  • 105
  • 121
  • Nice one. Wish I'd known this a while back. I got terribly confused. – spender Oct 10 '09 at 14:27
  • 4
    This is one of the worst examples of feature creep. Providing `InetAddress.getLoopbackAddress()` would be so much cleaner. I discovered this simply by incident. The address string in my application got nulled under some condition and instead of NPE my application still chugged alone. This has taught be a valueable lesson to read Java API carefully and with full attention. – Alexander Pogrebnyak Oct 12 '09 at 15:01
  • @AlexanderPogrebnyak, silly question... what about [InetAddress.isLoopbackAddress()](http://docs.oracle.com/javase/8/docs/api/java/net/InetAddress.html#isLoopbackAddress--)? – Gili Jul 07 '14 at 19:31
  • 2
    @Gili. The OPs original question was about accepting connections only from the localhost. `isLoopbackAddress` will not help you obtain the localhost IP address. – Alexander Pogrebnyak Jul 08 '14 at 15:33
  • Will it provide the loopback address of IP4 or IP6 protocol? Please dont write IP4 only code. We need to switch to IP6 soon. – Lothar Dec 07 '15 at 01:29
  • @Lothar InetAddress is a generic abstraction from IPv4 and IPv6. Please read documentation. I've updated the link to a modern javadoc – Alexander Pogrebnyak Dec 17 '15 at 14:51
7

If you want to limit connections from the localhost, then specify that when you open the ServerSocket. If you only listen on localhost, then you'll only get connections from localhost.

    int port = .....
    SocketAddress socketAddress = new InetSocketAddress("127.0.0.1", port);
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(socketAddress);
    serverSocket.accept();
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • It doesn't work. See: I'm on 192.168.0.1 and someone else on 192.168.0.2. I want to deny his access to my server socket listening on 192.168.0.1:port, but this solution doesn't work. It only caused that connecting to 127.0.0.1:port doesn't work from my own machine. – Mohsen Oct 09 '09 at 08:30
  • 2
    This is not an anwer to the question. Why is it incorrectly marked. The other anwers are also wrong in this case it should be left open and unanswered for all other people who come up with the same problem. – Lothar Dec 07 '15 at 01:31
3

Thanks skaffman. The following code worked with a little manipulation (hard-coding 127.0.0.1).

int port = .....
SocketAddress socketAddress = new InetSocketAddress("127.0.0.1", port);
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(socketAddress);
serverSocket.accept();

If I read local address from InetAddress.getLocalHost(), other network users on the same subnet are still able to see my server.

Mohsen.

Mohsen
  • 3,512
  • 3
  • 38
  • 66
  • D'oh, yes, I forgot that `InetAddess.getLocalHost()` doesn't give you 127.0.0.1, it gives the external IP address of that local host. My bad. – skaffman Oct 09 '09 at 09:00
  • Yes, I've found InetAddress.getLocalHost() doesn't really work as expected too. – spender Oct 09 '09 at 09:02
  • 1
    Be warned that the "I'm listening on 127.0.0.1 so only local users can connect to me" assumption sometimes fails - eg if you have a proxy running on your machine that can be coerced into connecting to 127.0.0.1 on behalf of a remote user. – caf Oct 10 '09 at 12:07