在渗透测试时,客户需要对我们的测试IP进行加白,但是此次客户要求精确到固定端口或者小范围端口(不能1-65535),根据以前的经验,默认是加白IP和全端口,因为代理建立连接使用的端口是随机的,所以这次算是从头查找资料总结一下各种指定源端口的方式。
这里的端口是指与目标建立连接时使用的源端口,而不是代理监听的端口。
最好使用服务器(VPS)发送请求。如果在局域网内向外网发起请求,即使本机指定了端口,也无济于事,因为实际发出请求的是最外层网络设备。
# 指定12345端口,缺点是一次一用,比较麻烦
nc <IP> <Port> -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后的端口连接。
自己实现一个代理。监听一个端口,然后将流量发送到代理中,再由代理去固定源端口发送请求并返回结果。
Warning
因为都是走的这个端口去建立连接,一旦出现异常情况,那这个端口可能会长期保持TIME\_WAIT
状态从而导致无法正常使用。
python代码如下:
import http.server # 导入HTTP服务器相关的模块
import socketserver # 导入socket服务器相关的模块
import http.client # 导入HTTP客户端相关的模块
import urllib.parse # 导入URL解析相关的模块
import socket # 导入socket相关的模块
from loguru import logger # 导入日志库
LISTEN\_PORT = 8080 # 本地监听端口
CONNECT\_PORT = 22333 # 用于建立代理服务器与目标服务器连接的本地端口
# 继承http.server.BaseHTTPRequestHandler类,实现代理服务器的请求处理
class ProxyRequestHandler(http.server.BaseHTTPRequestHandler):
# 处理CONNECT方法
def do\_CONNECT(self):
# 解析URL
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))
# 返回200连接已建立响应
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):
# 解析URL
u = urllib.parse.urlparse(self.path)
# 创建一个HTTP连接
conn = http.client.HTTPConnection(u.hostname, port=u.port or 80, timeout=10, source\_address=('0.0.0.0', CONNECT\_PORT))
# 发送HTTP请求
conn.request(self.command, self.path, headers=self.headers)
# 获取HTTP响应
resp = conn.getresponse()
# 发送HTTP响应头
self.send\_response(resp.status)
for header, value in resp.getheaders():
self.send\_header(header, value)
self.end\_headers()
# 发送HTTP响应体
while True:
data = resp.read(1024)
if not data:
break
self.wfile.write(data)
# 处理POST方法
def do\_POST(self):
# 解析URL
u = urllib.parse.urlparse(self.path)
# 获取请求体长度
content\_len = int(self.headers.get('Content-Length', 0))
# 读取请求体
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)) # 创建 HTTP 连接对象
conn.request(self.command, self.path, body=body, headers=self.headers) # 发送 HTTP POST 请求
resp = conn.getresponse() # 获取响应对象
self.send\_response(resp.status) # 发送 HTTP 响应状态码
for header, value in resp.getheaders(): # 遍历响应头部信息
self.send\_header(header, value) # 发送响应头部信息
self.end\_headers() # 结束响应头部信息的发送
while True:
data = resp.read(1024) # 按照每次读取 1024 字节的方式获取响应数据
if not data: # 如果读取完毕,跳出循环
break
self.wfile.write(data) # 将响应数据写入连接,响应给客户端
if \_\_name\_\_ == '\_\_main\_\_':
try:
# 创建一个 TCPServer 对象,绑定到 0.0.0.0:LISTEN\_PORT 的地址,用于监听来自客户端的连接请求,当有连接请求时,将使用 ProxyRequestHandler 类进行处理。
httpd = socketserver.TCPServer(('0.0.0.0', LISTEN\_PORT), ProxyRequestHandler)
logger.info(f"Proxy server is listening on port {LISTEN\_PORT}")
# 开始监听并接受来自客户端的连接请求,直到出现 KeyboardInterrupt 异常为止
httpd.serve\_forever()
except KeyboardInterrupt:
httpd.server\_close()
效果如下,均为22333
端口。
ssh -N -D 0.0.0.0:9999 ubuntu@hongkong
sudo socat TCP-LISTEN:<new\_source\_port>,fork,reuseaddr TCP:<destination\_IP>:<destination\_port>
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。