如果Java应用程序创建了一个接受TCP连接的ServerSocket
,是否有办法限制允许哪些进程连接到它?
例如,这是我目前的代码:
ServerSocket serverSocket = new ServerSocket(1234);
Socket socket = serverSocket.accept();
我想确保我的网络上的其他设备甚至是同一台机器上运行的其他进程无法连接到它(如果他们这样做将会带来安全风险)。我能够通过仅将serverSocket
绑定到环回地址来解决前者(检查指向本地主机的socket.getRemoteAddress()
是否也能正常工作)但我找不到将其限制为当前状态的方法过程
在Android上执行此操作时,这更是一个问题。在我的应用程序中,我想创建一个WebView
(由我的进程拥有)并将其指向serverSocket
,但我不希望其他应用程序能够连接到它。
有没有办法解决这个问题?
答案 0 :(得分:1)
您可以将其绑定到127.0.0.1
, [1] ,这可以防止localhost之外的任何进程看到它。但是localhost中的任何进程都可以连接到它。这就是它的用途。如果要将其限制为某些进程,则必须在协议中实施身份验证步骤。
很难理解为什么。如果您不能信任localhost中的其他进程,那么您通常会遇到一个相当大的问题,而不仅仅是这里。
[1]或者127.0.0.x
其中1 <= x <= 254.
使用像200这样的模糊数字可能有助于默默无闻,但它仍然不是很安全。
答案 1 :(得分:0)
您可以获得此类安全性
套接字并非设计用于限制不同的进程。
答案 2 :(得分:0)
我认为您不能阻止其他进程连接到ServerSocket但是您接受一个连接,您可以确定它是属于您还是属于某个其他进程。第一步是确定连接是否来自localhost:
InetSocketAddress remoteAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
String hostname = remoteAddress.getHostName();
if (!hostname.equals("localhost")) { socket.close(); }
或者,您可以将套接字绑定到环回地址,如127.0.0.1或0.0.0.0(如提到的EJP),并跳过此步骤。一旦你知道连接来自localhost所有你需要做的就是找到远程端口并找出你的进程是否拥有它。
int remotePort = remoteAddress.getPort();
if (ownPort(remotePort) == 1) { socket.close(); }
据我所知,Java没有可用于列出进程端口的API,但您绝对可以通过JNI实现。在Java方面,您需要以下内容:
private native int doOwnPort(int port);
在本土方面:
JNIEXPORT jint JNICALL Java_something_doOwnPort(JNIEnv *env, jobject object, jint port) {
long totalFDs = getdtablesize();
struct sockaddr_in sa;
struct stat sb;
// Iterate through all file descriptors
for (int i = 0; i < totalFDs; ++i) {
// Check if "i" is a valid FD
memset(&sb, 0, sizeof(sb));
if (fstat(i, &sb) < 0)
continue;
// Check if "i" is a socket
if (!S_ISSOCK(sb.st_mode))
continue;
// Get local address of socket with FD "i"
memset(&sa, 0, sizeof(sa));
socklen_t sa_len = sizeof(sa);
getsockname(i, (struct sockaddr*) &sa, &sa_len);
// Check if the port matches
if (sa.sin_port == port)
return 1; // We own the port
}
return -1; // We don't own the port
}
PS:此代码适用于Linux,但也适用于Android / Windows / OSX。
也许有一种更直接/有效的方法来检查端口是否由当前进程拥有而不必迭代FD表,但这是一个单独的问题。 HTH!
答案 3 :(得分:0)
我们已经看到一些应用程序使用localhost网络端口来处理敏感的IPC。我们不鼓励这种方法,因为这些接口可以被设备上的其他应用程序访问。相反,您应该使用可以进行身份验证的Android IPC机制,例如使用服务。 (比使用环回更糟糕的是绑定到INADDR_ANY,从那时起您的应用程序可能会从任何地方接收请求。)