在使用 PHP 编写基于 Socket 的服务端程序时,socket_accept() 是用于接受客户端连接的关键函数。尽管这个函数非常实用,但它本身并不具备访问控制的功能。如果你希望你的服务只允许特定的 IP 地址进行连接,就需要自己实现 IP 白名单的过滤机制。
本文将详细介绍如何在使用 socket_accept() 的服务中添加 IP 白名单功能,提升服务的安全性和控制能力。
首先,我们来看一个典型的使用 socket_accept() 的基本 Socket 服务结构:
$host = '0.0.0.0';
$port = 12345;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);
echo "服务器已启动,监听端口 $port...\n";
while (true) {
$clientSocket = socket_accept($socket);
// 此处将添加 IP 白名单过滤逻辑
}
默认情况下,以上代码将无限接受所有客户端的连接请求。为了加入 IP 白名单控制,我们需要在 socket_accept() 之后,使用 socket_getpeername() 获取客户端 IP,然后判断该 IP 是否在白名单中。
以下是修改后的代码,加入了简单的白名单机制:
$host = '0.0.0.0';
$port = 12345;
// IP 白名单
$whitelist = [
'192.168.1.100',
'203.0.113.45',
'198.51.100.23'
];
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);
echo "服务器已启动,监听端口 $port...\n";
while (true) {
$clientSocket = socket_accept($socket);
if ($clientSocket === false) {
continue;
}
socket_getpeername($clientSocket, $clientIp);
if (!in_array($clientIp, $whitelist)) {
echo "拒绝来自 $clientIp 的连接。\n";
socket_close($clientSocket);
continue;
}
echo "接受来自 $clientIp 的连接。\n";
// 此处处理客户端请求逻辑
$welcomeMsg = "欢迎访问 m66.net 的服务。\n";
socket_write($clientSocket, $welcomeMsg, strlen($welcomeMsg));
socket_close($clientSocket);
}
socket_getpeername():该函数用于获取已连接客户端的 IP 地址。
白名单数组:你可以将允许访问的 IP 地址放入 $whitelist 数组中。
连接控制:对于不在白名单中的 IP,我们直接使用 socket_close() 断开连接。
不建议将白名单硬编码在代码中,实际部署时可以从数据库或配置文件中动态加载。
可以考虑添加日志记录功能,追踪非法连接尝试。
通过在 socket_accept() 之后添加 IP 白名单验证逻辑,可以有效限制非授权的访问,提升 PHP Socket 服务的安全性。上述示例展示了一种最基础的实现方法,开发者可以根据实际需求进行扩展,例如加入 CIDR 范围、支持 IPv6 地址等。
在搭建对外提供服务的 PHP Socket 程序时,务必把好“第一道防线”,不要让不受信任的客户端轻易接入你的系统。希望本文对你有所帮助!