为何仅Google DNS服务器IP在端口扫描中返回开放端口?
问题原因分析
你的扫描逻辑仅对Google DNS(8.8.8.8/8.8.4.4)有效,其他IP全返回端口关闭,主要有以下几个关键原因:
1. Android环境下nc命令的行为差异
Android系统自带的nc一般是BusyBox精简版,和标准Linux的nc行为存在区别:
- 部分BusyBox的
nc在TCP连接成功但无数据交互时,会返回退出码1而非0。Google DNS的443端口是HTTPS,连接后服务器会主动发送响应数据;TCP 53端口(DNS-over-TCP)会保持连接等待请求,nc能快速判定连接成功返回0,但其他开放端口若没有主动数据交互,nc会直接退出返回1。 - 你当前的命令未设置超时时间,
nc可能在等待连接超时过程中被系统强制终止,导致退出码非0,但Google DNS网络延迟极低,连接能快速建立,因此能正确返回0。
2. 目标主机的网络防护策略
大部分公网IP和本地设备的前100端口,要么本身处于关闭状态,要么被防火墙/安全组拦截:
- 公网主机通常仅开放少量业务端口,前100端口大多关闭或被拦截,此时
nc连接会被拒绝,返回退出码1。 - 本地设备可能受系统防火墙(如Android自身防火墙、路由器防火墙)限制,拦截了端口扫描请求,导致连接失败。
3. TCP与UDP扫描未区分
你提到要测试TCP和UDP端口,但当前代码中的nc命令默认是TCP连接,扫描UDP端口需要添加-u参数(nc -u $host $port)。如果代码未区分TCP和UDP的扫描命令,UDP端口的扫描结果必然全部错误,而Google DNS的53端口TCP是开放的,所以能被正确识别,这也解释了为何只有这两个IP的53和443端口能被扫出。
4. Android的网络权限与进程限制
虽然你能连接Google DNS,但Android系统对第三方应用的网络操作有严格限制:
- Android 9及以上版本默认启用明文流量限制,若目标主机未使用HTTPS,连接可能被系统拦截(但Google DNS的443是HTTPS、53是DNS不受此限制)。
- Runtime.exec启动的子进程可能未继承应用的网络权限,或受SELinux策略限制,导致无法正常连接其他主机。
解决方案建议
你提到的Socket类方案是Android端端口扫描更可靠的选择,原因如下:
- 直接使用Java/Kotlin的
Socket(TCP)和DatagramSocket(UDP)类,能精准控制连接超时、数据交互,不受nc命令版本差异影响。 - 可自定义超时时间,避免长时间等待,提升扫描效率。
- 能直接捕获连接异常(如
ConnectException表示端口关闭/被拦截),比依赖进程退出码更可靠。
示例TCP扫描代码(Kotlin):
fun scanTcpPort(host: String, port: Int, timeout: Int = 1000): Boolean { return try { Socket().use { socket -> socket.connect(InetSocketAddress(host, port), timeout) true } } catch (e: IOException) { false } }
UDP扫描需发送测试数据并等待响应,示例:
fun scanUdpPort(host: String, port: Int, timeout: Int = 1000): Boolean { return try { DatagramSocket().use { socket -> socket.soTimeout = timeout val sendData = "test".toByteArray() val packet = DatagramPacket(sendData, sendData.size, InetAddress.getByName(host), port) socket.send(packet) val receivePacket = DatagramPacket(ByteArray(1024), 1024) socket.receive(receivePacket) true } } catch (e: IOException) { false } }
内容的提问来源于stack exchange,提问作者user9257314
相关产品推荐
相关产品推荐

