Нат ПТК дырокол в Python - PullRequest
0 голосов
/ 01 мая 2020

Задача

Я пытаюсь реализовать соединение Peer2Peer между двумя компьютерами через inte rnet для обмена данными без промежуточного сервера в python. По возможности я также хочу использовать TCP-протокол для проверки достоверности данных. Пересылка портов Stati c не подходит, так как я хочу использовать ее в разных сетях, поэтому я хотел дать шанс пробить NAT-дыру и столкнулся с некоторыми проблемами.

Проблема

Следуя ресурсам Википедии и пытаясь реализовать обмен пакетом SYN, мне было интересно, как мне создать пакет SYN. Мне кажется, что функция отправки пакета в несвязанное соединение возможна только с UDP и функцией sendto ().

Также, как мне прослушать пакет SYN? Обе стороны должны привязать свой сокет к локальному адресу 0.0.0.0, так как никто не может знать, какой пакет передается первым.

Идея

Компьютер A хочет отправить компьютеру B файл:

  • A отправляет SYN на B (но NAT не пересылает его, поскольку внутри локальной сети нет открытого соединения)
  • B отправляет SYN на A (должно достигать A , потому что A открыл соединение с его отправкой)
  • A получает SYN и отвечает на B (возможно, связывает сокет и предпочтительнее разрешающие стандартные методы сокетов)
  • A и B знают друг друга и должны быть в состоянии общаться через TCP-сокеты

Код

Источник этого кода отсюда Ссылка , и мне кажется, что он работает без ручного обмена пакетами SYN, но когда я попытался перенести его на python, возникла проблема с привязкой к локальному IP-адресу.

import socket
import threading
import _thread
import tqdm
import os
import sys
import urllib.request
class HolePunching(threading.Thread):
    def __init__(self, local_port, public_port):
        self.local_host = ""
        self.local_port = local_port
        self.public_host = ""
        self.public_port = public_port
        self.punchSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.punchSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
        self.public_host = self.getPublicIp()
        self.local_host = "10.0.0.6"
    def getPublicIp(self):
        ip = urllib.request.urlopen("https://api.ipify.org").read().decode('utf8')
        return ip
    def run(self):
        holePunch = HolePunching(self.local_port,self.public_port)
        holePunch.RunImpl()
    def RunImpl(self):
        self.PunchHole()
        self.RunServer()
        print("komttm noch")

    def PunchHole(self):
        print(f"Punching hole on {self.local_host}:{self.local_port}")
        try:
            self.punchSocket.bind((self.local_host,self.local_port))
            self.punchSocket.connect((self.public_host,self.public_port))
            print("Hole was punched")
        except socket.error as er:
            print(f"Fehler beim Binden des Sockets {str(er)}")
            self.punchSocket.close()


    def RunServer(self):
        self.serverSocket.bind((self.local_host, self.local_port))
        self.serverSocket.listen(2)

        while (True):
            clientSocket = self.serverSocket.accept()
            _thread.start_new_thread(self.ProcessConnection(clientSocket))

    def ProcessConnection(self, connectionSocket):
        print(f"Socket accepted")
        print("Do stuff")

        connectionSocket.close()


print("Running")
HolePunching(5000,5001).run()

Это сообщение об ошибке, которое я получаю.

Fehler beim Binden des Sockets [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat

Большое спасибо за ваше время в ответе g мои вопросы!

...