В настоящее время я кодирую прокси-сервер только из сокета и модуля ssl. Я следовал различным исходным кодам, в результате чего получился следующий код.
def main():
global listen_port, buffer_size, max_conn
try:
listen_port = int(input("Enter a listening port: "))
except KeyboardInterrupt:
sys.exit(0)
max_conn = 5
buffer_size = 1024
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("[*] Intializing socket... Done")
s.bind(('', listen_port))
print("[*] Socket binded sucessfully...")
s.listen(max_conn)
print("[*] Socket started successfully [{}]".format(listen_port))
except Exception as e:
print(e)
sys.exit(2)
while True:
try:
conn, addr = s.accept()
conn.settimeout(10)
print("[*] New connection established")
try:
data = conn.recv(buffer_size)
except socket.timeout as e:
print('[*] Client Timeout')
start_new_thread(conn_string, (conn, data, addr))
except KeyboardInterrupt:
s.close()
print("\n[*] Shutting down...")
sys.exit(1)
s.close()
def conn_string(conn, data, addr):
try:
data_str = data.decode("utf-8")
first_line = data_str.split("\n")[0]
url = first_line.split(" ")[1]
http_pos = url.find("://")
if http_pos == -1:
temp = url
else:
temp = url[(http_pos + 3):]
port_pos = temp.find(":")
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if port_pos == -1 or webserver_pos < port_pos:
port = 80
webserver = temp[:webserver_pos]
else:
port = int(temp[(port_pos + 1):][:webserver_pos - port_pos - 1])
webserver = temp[:port_pos]
proxy_server(webserver, port, conn, data, addr)
except Exception as e:
print(e)
def access_control(webserver):
access_control_list = ['sing.cse.ust.hk']
access_flag = False
for i in range(0, len(access_control_list)):
if(access_control_list[i] in webserver):
access_flag = False
break
else:
access_flag = True
return access_flag
def proxy_server(webserver, port, conn, data, addr):
try:
access = access_control(webserver)
if(access):
print("[*] Connecting to " + webserver + ' with port ' + str(port))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
if(port == 80):
s.connect((webserver, port))
s.send(data)
elif(port == 443):
request = "GET / HTTP/1.1\r\nHost: " + webserver + "\r\nProxy-Connection: Keep-Alive\r\n\r\n"
#print(request)
wrapped_s = ssl.create_default_context().wrap_socket(s, server_hostname=webserver)
#wrapped_s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1_2)
wrapped_s.connect((webserver, port))
wrapped_s.send(request.encode('utf-8'))
while True:
try:
if(port == 80):
reply = s.recv(buffer_size)
elif(port == 443):
reply = wrapped_s.recv(buffer_size)
except socket.timeout as e:
print('[*] Server Timeout')
break
if len(reply) > 0:
#print(reply.decode("utf-8"))
conn.send(reply)
print("[*] Request done: " + webserver + " with port " + str(port))
else:
print(webserver + ' ' + 'Fail')
break
if(port == 443):
wrapped_s.close()
s.close()
else:
conn.send(str.encode("HTTP/1.1 404 Not Found\n"+"Content-Type: text/html\n"+"\n"+"<html><body>404 Page Not Found</body></html>\n"))
print("access Deny")
conn.close()
print("Connection Closed")
except socket.error as e:
print(e)
s.close()
conn.close()
sys.exit(1)
Цель этого кода - запустить локальный прокси-сервер, обрабатывающий запросы HTTP и HTTPS, и немного контроля доступа.
Компонент HTTP и контроля доступа выполнен и протестирован, и HTTPS-запросы успешно переписываются и отправляются адресату.
Я попытался распечатать ответ, полученный с веб-сервера, содержимое там и код состояния - 200.
Но когда код пытается записать данные в клиентский сокет. Ошибка [WinError 10054] Существующее соединение было принудительно закрыто приглашением удаленного хоста и остановило программу.
Пример вывода для подключения к https://www.example.com:
Enter a listening port: 4444
[*] Intializing socket... Done
[*] Socket binded sucessfully...
[*] Socket started successfully [4444]
[*] New connection established
[*] Connecting to example.com with port 443
[*] Request done: example.com with port 443
[*] Request done: example.com with port 443
[WinError 10054] An existing connection was forcibly closed by the remote host
Я проверил поведение в Microsoft Edge и Firefox, оба не могут показать веб-страницу. Сообщение об ошибке, отображаемое в Firefox, является Код ошибки: SSL_ERROR_RX_RECORD_TOO_LONG
Я изменил MAX_TLS_VERSION в Firefox на TLS 1.2, но не повезло.
Любая идея, почему соединение внезапно прекращается?