【问题标题】:How to determine an incoming connection is from local machine如何确定传入连接来自本地计算机
【发布时间】:2010-12-05 06:32:50
【问题描述】:

我有一个接受传入连接的 SocketServer。出于安全原因,我应该只允许本地连接(来自运行服务器的机器的连接)。

如何确定传入连接是否来自另一台计算机?以下代码对此是否安全?

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

fromThisMachine() 方法是这样的:

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;
}

谢谢, 莫森

【问题讨论】:

    标签: java networking sockets network-programming


    【解决方案1】:

    InetAddress.getByName( null ) 总是返回环回地址。见javadoc

        int port = .....
        SocketAddress socketAddress =
            new InetSocketAddress( InetAddress.getByName( null ), port);
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(socketAddress);
        serverSocket.accept();
    

    【讨论】:

    • 不错的一个。希望我早点知道这一点。我非常困惑。
    • 这是功能蠕变最糟糕的例子之一。提供InetAddress.getLoopbackAddress() 会更干净。我只是偶然发现了这一点。我的应用程序中的地址字符串在某些情况下被清空,而不是 NPE,我的应用程序仍然单独运行。这教会了仔细和全神贯注地阅读 Java API 是很有价值的一课。
    • @AlexanderPogrebnyak,愚蠢的问题...InetAddress.isLoopbackAddress() 呢?
    • @吉利。 OPs 最初的问题是关于只接受来自本地主机的连接。 isLoopbackAddress不会帮你获取本地IP地址。
    • 会提供IP4或IP6协议的环回地址吗?请不要编写仅 IP4 的代码。我们需要尽快切换到 IP6。
    【解决方案2】:

    如果您想限制来自 localhost 的连接,请在打开 ServerSocket 时指定。如果你只在 localhost 上监听,那么你只会从 localhost 获得连接。

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

    【讨论】:

    • 它不起作用。请参阅:我在 192.168.0.1 上,其他人在 192.168.0.2 上。我想拒绝他访问我在 192.168.0.1:port 上监听的服务器套接字,但这个解决方案不起作用。它只是导致连接到 127.0.0.1:port 在我自己的机器上不起作用。
    • 这不是问题的答案。为什么标记不正确。在这种情况下,其他答案也是错误的,对于提出相同问题的所有其他人,它应该保持开放和无人回答。
    【解决方案3】:

    谢谢斯卡夫曼。下面的代码进行了一些操作(硬编码 127.0.0.1)。

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

    如果我从 InetAddress.getLocalHost() 读取本地地址,同一子网上的其他网络用户仍然可以看到我的服务器。

    莫森。

    【讨论】:

    • D'oh,是的,我忘记了 InetAddess.getLocalHost() 没有给你 127.0.0.1,它给出了该本地主机的外部 IP 地址。我的错。
    • 是的,我发现 InetAddress.getLocalHost() 也没有按预期工作。
    • 请注意,“我正在监听 127.0.0.1,因此只有本地用户可以连接到我”假设有时会失败 - 例如,如果您的计算机上运行了可以强制连接的代理代表远程用户到 127.0.0.1。
    猜你喜欢
    • 1970-01-01
    • 2011-09-02
    • 2012-05-30
    • 2017-11-22
    • 1970-01-01
    • 2012-05-19
    • 2016-08-27
    • 1970-01-01
    • 2017-06-16
    相关资源
    最近更新 更多