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

9
我有一个Java应用程序(不在任何应用程序容器中运行),它侦听ServerSocket以获取连接。我希望它只接受来自本地主机的连接。目前,在接受连接之后,它会检查对等IP并拒绝它,如果它不是环回地址,但我知道对等IP地址可能会被欺骗。因此,如果可能的话,我更喜欢绑定到仅侦听环回接口的套接字;这是可能的吗?
我已经尝试了一些不同的方法(例如在调用bind()时指定“127.0.0.1”作为本地地址),但没有成功。
更新:
我很尴尬地承认这全是我的错。我们的应用程序侦听两个不同的端口,我将其中一个绑定到环回接口,但针对另一个进行测试。当我实际尝试使用telnet连接到正确的端口时,一切正常(即,绑定到“127.0.0.1”恰好执行了它应该执行的操作)。
至于欺骗环回地址,你们是对的。我不应该让它听起来像是主要问题。实际上,期望的行为是仅接受本地连接,并且仅绑定到本地接口比接受所有连接然后关闭非本地连接更直接。

你从哪里得到的信息说127.0.0.1可以被伪造?我对此表示怀疑。 - Stu Thompson
5个回答

8

这种方式无法欺骗同行IP地址,因此您在使用检查对等方并决定在建立期间断开连接技术时无需担心。

但是:绑定到127.0.0.1应该可以工作,并且会导致操作系统告诉连接主机,如果它们连接到系统的其他IP地址之一,则没有任何内容正在侦听。您能否用一个可编译的示例修改此问题?也许您犯了一个简单的错误。


3
if (socket.getInetAddress().isLoopbackAddress()){
    //Your code goes here
}

尽管代码本身可以表达,但仅有代码的答案是不被鼓励的。请考虑添加文档参考、功能描述等内容。 - edmz

3
您可以像您已经在做的那样,接受连接,然后使用getInetAddress()确保地址是授权的。如果不是,则立即关闭socket。127.0.0.1不能被欺骗。或者,您可以安装自己的安全管理器,它将调用其checkAccept()方法并提供远程站点的地址和端口。这有点困难 - 我从未尝试过,因为第一种解决方案对我来说始终足够。

1
原帖已经说了他正在这样做,但是不想这样做,因为远程端可能会被“欺骗”或其他什么原因。 - Jerub
1
Jerub:OP 不理解欺骗攻击。 Pax:任何旧的安全管理器都可以,你只需要设置一个策略,给代码正确的权限(permission java.net.SocketPermission "127.0.0.1" "listen,accept" 或类似的内容——需要从 accept 捕获 SecurityException)。 - Tom Hawtin - tackline

3
如果对等地址被欺骗,那么你无法再做更多的事情。
然而,欺骗127.0.0.1并不容易。你必须拥有一个足够愚蠢的TCP/IP堆栈才能接受这样的数据包。欺骗者没有办法接收回传的数据包。在一个好的TCP/IP堆栈上,它不应该能够猜测序列号,因此无法跟上预期的对话。

1

当您绑定ServerSocket时,指定localhost应该使TCP/IP堆栈拒绝连接。即使在您的系统上无法正常工作,由于该地址未通过物理接口路由,因此无法欺骗localhost(好吧,也许如果有人黑了您的TCP/IP堆栈和默认网关路由器)。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接