如何确定传入连接来自本地计算机

Posted

技术标签:

【中文标题】如何确定传入连接来自本地计算机【英文标题】: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;

谢谢, 莫森

【问题讨论】:

【参考方案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。

以上是关于如何确定传入连接来自本地计算机的主要内容,如果未能解决你的问题,请参考以下文章

mstsc连接远程桌面如何挂载本地磁盘

SecureCRT工具如何连接本地虚拟机

如何确定连接错误是由于测试还是主机造成的

怎么打开共享文件夹?

vmware中的虚拟机和本地主机如何设置在同一网段

怎么将本地文件传到阿里云服务器里面