PHP实现在线端口扫描
字数 792 2025-08-18 11:39:19
PHP实现简易在线端口扫描器教学文档
一、技术原理
PHP通过fsockopen()函数实现端口扫描功能,该函数用于打开网络套接字连接。
fsockopen函数说明
fsockopen(
string $hostname,
int $port = -1,
int &$errno = null,
string &$errstr = null,
float $timeout = ini_get("default_socket_timeout")
): resource|false
参数说明:
$hostname: 目标主机名或IP地址$port: 要连接的端口号$errno: 错误编号(引用传递)$errstr: 错误信息(引用传递)$timeout: 连接超时时间(秒)
二、实现步骤
1. 获取扫描参数
- 目标IP地址
- 待扫描的端口列表(默认值:21,23,25,79,80,110,135,137,138,139,143,443,445,1433,3306)
2. 端口扫描核心逻辑
function getOpenPort($ip, $port) {
$msg = array('Ftp','Telnet','Smtp','Finger','Http','Pop3','Location Service',
'Netbios-NS','Netbios-DGM','Netbios-SSN','IMAP','Https',
'Microsoft-DS','MSSQL','MYSQL');
foreach ($port as $key => $value) {
echo $value.'  ';
echo $msg[$key].'  ';
$fp = @fsockopen($ip, $value, $errno, $errstr, 0.5);
$result = $fp ? '<font color="#43CD80"><开启></font><br>'
: '<font color="#FF6347"><关闭></font><br>';
echo $result;
}
}
3. SSRF漏洞防护
防止扫描内网地址的黑名单机制:
$blackHostlist = array("172.", "10.", "localhost", "127.", "192.");
foreach($blackHostlist as $blackHost) {
if(strpos($ip, $blackHost) === 0) {
echo '<script>alert("禁止扫描内网地址!");</script>';
die();
}
}
三、完整代码实现
前端表单 (index.html)
<form method="post" action="scan.php">
目标IP - IP Address: <input type="text" name="ip" id="domain"><br><br>
扫描端口 - Ports: <input type="test" name="port" value="21,23,25,79,80,110,135,137,138,139,143,443,445,1433,3306"><br><br>
开始扫描 - Start: <input type="submit" value="点击开始扫描 - Scaning">
</form>
后端处理 (scan.php)
<?php
function getOpenPort($ip, $port) {
$msg = array('Ftp','Telnet','Smtp','Finger','Http','Pop3','Location Service',
'Netbios-NS','Netbios-DGM','Netbios-SSN','IMAP','Https',
'Microsoft-DS','MSSQL','MYSQL');
foreach ($port as $key => $value) {
echo $value.'  ';
echo $msg[$key].'  ';
$fp = @fsockopen($ip, $value, $errno, $errstr, 0.5);
$result = $fp ? '<font color="#43CD80"><开启></font><br>'
: '<font color="#FF6347"><关闭></font><br>';
echo $result;
}
}
$ip = $_POST['ip'];
$port = explode(',', $_POST['port']);
$blackHostlist = array("172.", "10.", "localhost", "127.", "192.");
foreach($blackHostlist as $blackHost) {
if(strpos($ip, $blackHost) === 0) {
echo '<script>alert("禁止扫描内网地址!");</script>';
die();
}
}
getOpenPort($ip, $port);
?>
四、关键点说明
-
超时设置:
fsockopen的timeout参数设置为0.5秒,平衡响应速度和准确性 -
错误抑制:使用
@符号抑制连接失败时的错误输出 -
端口服务映射:数组
$msg将端口号映射为常见服务名称 -
结果可视化:使用不同颜色区分开放(绿色)和关闭(红色)的端口
-
输入处理:将逗号分隔的端口字符串转换为数组
explode(',', $_POST['port'])
五、安全注意事项
-
SSRF防护必须实现,防止被用来扫描内网
-
可扩展的黑名单:可根据需要添加更多内网IP段
-
输入验证:建议增加对IP地址格式的验证
-
权限控制:实际应用中应考虑添加身份验证机制
-
日志记录:记录扫描请求,便于审计
六、优化建议
- 增加多线程/异步扫描提高效率
- 添加扫描进度显示
- 实现更友好的错误处理
- 增加扫描历史记录功能
- 添加端口描述信息的自动获取
这个简易端口扫描器适合学习网络编程基础,实际生产环境使用需要考虑更多安全性和性能因素。