什么是TCP代理
TCP代理是一種網路代理技術,它允許客戶端和服務器之間通過一個位于中間的第三方TCP代理服務器進行通信,TCP代理的作業方式是客戶端向代理服務器發送TCP連接請求,代理服務器將此請求轉發到目標服務器,然后等待目標服務器回應,當目標服務器回應時,代理服務器將回應轉發回客戶端,
整體功能規劃
(1)顯示本地設備與遠程設備之間的通信程序
(2)處理代理兩端發送和接收的資料
(3)創建和管理socket
列印設備之間的通信程序
# 所有可列印字符(長度為3)保持不變,不可列印字符改為句點“.”表示
# chr函式用于將i轉換為相應的ASCII字符
# repr函式回傳一個物件的字串表示形式,通常用于除錯和列印目的,對于大多數字符,repr(chr(i))回傳一個長度為 3 的字串,其中第一個和最后一個字符是單引號(')或雙引號("),中間的字符是該字符本身
HEX_FILTER = ''.join([(len(repr(chr(i))) == 3) and chr(i) or '.' for i in range(256)])
# hexdump函式能接收bytes或string型別的輸入,并將其轉換為十六進制格式輸出到螢屏上
# 它能同時以十六進制數和ASCII可列印字符的格式,輸出資料包的詳細內容,
# 這有助于理解未知協議的格式,或是在明文協議里查找用戶的身份憑證等
def hexdump(src, length=16, show=True):
# 如果傳進來的引數是bytes型別,呼叫decode函式將它轉換為string型別
if isinstance(src, bytes):
src = https://www.cnblogs.com/Timesi/archive/2023/03/25/src.decode()
results = list()
for i in range(0, len(src), length):
# 從src中取出一段資料放入word變數
word = str(src[i : i + length])
# 呼叫內置的translate函式把整段資料轉換成可列印字符的格式,保存到printable變數里,HEX_FILTER為翻譯表
printable = word.translate(HEX_FILTER)
# 將word中的資料轉換為十六進制保存在變數hexa中
hexa =' '.join([f'{ord(c):02x}' for c in word])
hexwidth = length * 3
# 將word變數起始點的偏移、其十六進制表示和可列印字符表示形式打包成一行字串,放入results陣列
results.append(f'{i : 04x} {hexa:<{hexwidth}} {printable}')
if show:
for line in results:
print(line)
else:
return results
處理代理兩端發送和接收的資料
# 從代理兩端接收資料
def receive_from(connection):
# 用來存盤socket物件回傳的資料
buffer = b""
connection.settimeout(5)
try:
# 創建一個回圈,不斷把回傳的資料寫進buffer,直到資料讀完或者連接超時為止,最后,把buffer回傳給呼叫方.
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except Exception as e:
pass
return buffer
def request_handler(buffer):
# 此處可添加修改請求包操作
return buffer
def response_handler(buffer):
# 此處可添加修改回傳包操作
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
# 連接遠程主機
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
# 進入主回圈之前,先確認是否需要先從遠端設備接收資料
if receive_first:
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print("[<==] sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
while True:
# 從本地客戶端讀取資料,列印本地資料,處理請求資料,轉發給遠程服務器
local_buffer = receive_from(client_socket)
if len(local_buffer):
line = "[==>]Received %d bytes from localhost." % len(local_buffer)
print(line)
hexdump(local_buffer)
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
# 從遠程服務器讀取資料,列印遠端資料,處理回應資料,轉發給本地客戶端
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[<==]Received %d bytes from remote." % len(remote_socket))
hexdump(local_buffer)
remote_buffer = request_handler(remote_buffer)
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
# 當通信兩端都沒有任何資料時關閉兩端的socket,退出代理回圈
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print("[*]No more data. closing connections.")
break
創建和管理socket
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 創建一個socket并系結到本地埠開始監聽
try:
server.bind((local_host, local_port))
except Exception as e:
print(" problem on bind: %r" % e)
print("[!!] Failed to listen on %s:%d" % (local_host, local_port))
print("[!!] check for other listening sockets or correct permissions. ")
sys.exit(e)
print("[*] Listening on %s: %d" % (local_host, local_port))
server.listen(5)
# 每出現一個新連接就新開一個執行緒,將新連接交給proxy_handler函式
while True:
client_socket, addr = server.accept()
line = "> Received incoming connection from %s:%d" % (addr[0], addr[1])
print(line)
proxy_thread = threading.Thread(
target=proxy_handler,
args=(client_socket, remote_host, remote_port, receive_first)
)
proxy_thread.start()
整體代碼
完整代碼可以參考我的Github倉庫:Github
代碼測驗
這里使用kali虛擬機(192.168.131.135)作為本地機器,使用ubuntu虛擬機(192.168.131.132)作為TCP代理機器和FTP服務器,
首先在ubuntu上運行該代碼:

接著,在本地kali機器上連接ubuntu的9000埠進行登錄:

此時可以看到ubuntu機器上已經列印出了資料:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/548176.html
標籤:其他
