限定源端口访问目标
字数 824 2025-08-10 23:41:50
限定源端口访问目标技术指南
1. 背景与概念
在渗透测试或网络安全操作中,有时需要将测试IP加入白名单,但客户可能要求精确到固定端口或小范围端口(不能是1-65535全端口)。这种情况下,需要控制与目标建立连接时使用的源端口。
重要注意事项
- 服务器环境要求:最好使用VPS服务器发送请求。在局域网内向外网发起请求时,即使本机指定了端口,实际发出请求的是最外层网络设备,本机设置无效。
- 端口概念:这里指的是与目标建立连接时使用的源端口,而非代理监听的端口。
2. 实现方法
方法一:使用NC(netcat)工具
nc <目标IP> <目标端口> -p 12345
特点:
- 简单直接
- 一次一用,比较麻烦
- 只能用于单次连接
方法二:批量占用端口法
通过Python脚本强制占用所有可用端口,使代理发起请求时自动选择未被占用的端口(高段端口)。
import socket
import time
# 配置参数
start_port = 1 # 起始端口
end_port = 60000 # 结束端口
# 创建套接字列表
socks = []
for port in range(start_port, end_port+1):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', port))
sock.listen(1)
socks.append(sock)
except:
print(f"{port} 被其他应用占用")
print(f'已占用端口范围: {start_port} - {end_port}')
# 长期保持端口占用
while True:
time.sleep(60)
效果:
- 代理将被迫使用60000以上的端口进行连接
- 实现了源端口范围的控制
方法三:手动实现代理转发
自己实现代理服务,监听一个端口,然后固定源端口发送请求。
警告:
- 所有连接都使用同一端口,可能出现TIME_WAIT状态导致端口无法使用
import http.server
import socketserver
import http.client
import urllib.parse
import socket
from loguru import logger
# 配置参数
LISTEN_PORT = 8080 # 本地监听端口
CONNECT_PORT = 22333 # 用于建立连接的本地源端口
class ProxyRequestHandler(http.server.BaseHTTPRequestHandler):
# 处理CONNECT方法(HTTPS)
def do_CONNECT(self):
u = urllib.parse.urlparse('http://' + self.path)
p_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
p_sock.bind(('0.0.0.0', CONNECT_PORT))
p_sock.connect((u.hostname, u.port or 80))
self.wfile.write(b'HTTP/1.1 200 Connection Established\r\n\r\n')
p_sock.setblocking(False)
self.connection.setblocking(False)
while True:
try:
data = self.connection.recv(1024)
if not data: break
p_sock.sendall(data)
except: pass
try:
data = p_sock.recv(1024)
if not data: break
self.connection.sendall(data)
except: pass
self.connection.close()
p_sock.close()
# 处理GET方法
def do_GET(self):
u = urllib.parse.urlparse(self.path)
conn = http.client.HTTPConnection(u.hostname, port=u.port or 80,
timeout=10, source_address=('0.0.0.0', CONNECT_PORT))
conn.request(self.command, self.path, headers=self.headers)
resp = conn.getresponse()
self.send_response(resp.status)
for header, value in resp.getheaders():
self.send_header(header, value)
self.end_headers()
while True:
data = resp.read(1024)
if not data: break
self.wfile.write(data)
# 处理POST方法
def do_POST(self):
u = urllib.parse.urlparse(self.path)
content_len = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_len)
conn = http.client.HTTPConnection(u.hostname, port=u.port or 80,
timeout=10, source_address=('0.0.0.0', CONNECT_PORT))
conn.request(self.command, self.path, body=body, headers=self.headers)
resp = conn.getresponse()
self.send_response(resp.status)
for header, value in resp.getheaders():
self.send_header(header, value)
self.end_headers()
while True:
data = resp.read(1024)
if not data: break
self.wfile.write(data)
if __name__ == '__main__':
try:
httpd = socketserver.TCPServer(('0.0.0.0', LISTEN_PORT), ProxyRequestHandler)
logger.info(f"Proxy server is listening on port {LISTEN_PORT}")
httpd.serve_forever()
except KeyboardInterrupt:
httpd.server_close()
效果:
- 所有对外连接均使用固定的22333源端口
- 支持HTTP/HTTPS协议
3. 尝试过但失败的方法
以下方法经测试无法实现限定源端口的功能:
-
Nginx反向代理:
- 无法控制源端口
-
SSH动态代理:
ssh -N -D 0.0.0.0:9999 ubuntu@hongkong- 无法指定源端口
-
socat工具:
sudo socat TCP-LISTEN:<new_source_port>,fork,reuseaddr TCP:<destination_IP>:<destination_port>- 虽然可以监听指定端口,但无法控制源端口
4. 方法选择建议
- 简单临时需求:使用NC方法
- 需要大范围端口控制:使用批量占用端口法
- 需要精确固定端口:使用自定义代理方法
- 避免使用:Nginx反向代理、SSH动态代理和socat方法(对源端口控制无效)
5. 技术原理总结
控制源端口的关键在于:
- 在建立TCP连接时强制绑定特定的本地端口
- 通过占用低端口段迫使系统选择高端口
- 通过自定义代理中间层实现端口固定
以上方法在实际应用中可根据具体场景和需求灵活选择。