如何让套接字仅接受来自本地主机的连接(在 Java 中)?

Posted

技术标签:

【中文标题】如何让套接字仅接受来自本地主机的连接(在 Java 中)?【英文标题】:How do I have a socket accept connections only from the localhost (in Java)? 【发布时间】:2010-09-11 01:43:30 【问题描述】:

我有一个 java 应用程序(不在任何应用程序容器中运行),它在 ServerSocket 上侦听连接。我希望它只接受来自本地主机的连接。目前,在接受连接后,它会检查对等 IP,如果它不是环回地址,则拒绝它,但我知道对等 IP 地址可以被欺骗。所以,如果可能的话,我宁愿绑定到一个只监听环回接口的套接字;这可能吗?

我尝试了一些不同的方法(例如在调用 bind() 时将“127.0.0.1”指定为本地地址),但都没有成功。提前致谢。


感谢大家的帮助。我很尴尬地承认这都是我的错。我们的应用程序监听两个不同的端口,我将一个绑定到环回接口,但对另一个进行测试。当我实际尝试远程登录到正确的端口时,一切正常(即绑定到“127.0.0.1”完全符合预期)。

至于欺骗环回地址,你们是对的。我不应该让它听起来像主要关注点。确实,期望的行为是只接受本地连接,并且只绑定到本地接口是一种比接受所有连接然后关闭非本地连接更直接的方法。

【问题讨论】:

你从哪里得到127.0.0.1可以被欺骗的信息?我很怀疑。 【参考方案1】:

不能以这种方式欺骗对等 IP 地址,您不必担心使用检查对等并决定在建立期间断开连接的技术。

但是:绑定到 127.0.0.1 应该可以工作,并导致操作系统告诉连接主机,如果它们连接到其他 IP 地址的系统之一,则没有任何监听。你能用一个可编译的例子来修改这个问题吗?也许你犯了一个简单的错误。

【讨论】:

【参考方案2】:

如果对等地址被欺骗,那么您将无能为力。

然而,欺骗 127.0.0.1 并不容易。您必须有一个足够愚蠢的 TCP/IP 堆栈才能接受这样的数据包。欺骗者将无法接收数据包。在良好的 TCP/IP 堆栈上,它应该无法猜测序列号,因此无法跟上预期的对话。

【讨论】:

【参考方案3】:

您可以,正如您似乎已经在做的那样,无论如何都接受()连接,然后使用 getInetAddress() 来确保地址是授权的。如果没有,只需立即关闭()套接字。 127.0.0.1 不是一个可以被欺骗的地址。

或者,您可以安装自己的安全管理器,该管理器将使用远程站点的地址和端口调用其 checkAccept() 方法。这有点难 - 我从来没有尝试过,因为第一个解决方案对我来说总是足够的。

【讨论】:

原发帖人已经说过他正在这样做,但不想这样做,因为远程端可能被“欺骗”或其他什么。 Jerub:OP 不理解欺骗行为。 Pax:任何旧的安全管理器都可以,您只需要设置一个策略,为代码提供正确的权限(权限 java.net.SocketPermission "127.0.0.1" "listen,accept" 或类似的东西 - 需要捕获 SecurityException从接受)。【参考方案4】:
if (socket.getInetAddress().isLoopbackAddress())
    //Your code goes here

【讨论】:

尽管代码表达了自己,但不鼓励仅使用代码的答案。考虑添加文档参考、它的作用等等。【参考方案5】:

当您绑定 ServerSocket 时,指定 localhost 应该会使 TCP/IP 堆栈拒绝连接。即使这在您的系统上不起作用,localhost 也不能​​被欺骗(好吧,也许如果有人入侵了您的 TCP/IP 堆栈和默认网关路由器),因为该地址不是通过物理接口路由的。

我很好奇为什么您的绑定不成功,您的操作系统、Java 版本等是什么?

【讨论】:

以上是关于如何让套接字仅接受来自本地主机的连接(在 Java 中)?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 netcat 接受来自 LAN 外部的连接?

C++ Winsock API如何在接受连接之前获取连接客户端IP?

本地主机拒绝来自应用程序的连接

Vmware虚拟机如何和主机联网?

如何将java套接字连接到远程服务器套接字

使服务器应用程序仅接受来自同一主机中客户端应用程序的请求