views:

333

answers:

3

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

+3  A: 

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();

edited to use hard-coded 127.0.0.1

skaffman
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
+1  A: 

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
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
Yes, I've found InetAddress.getLocalHost() doesn't really work as expected too.
spender
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
+3  A: 

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
Nice one. Wish I'd known this a while back. I got terribly confused.
spender
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