apppublic/appPublic/across_nat.py

110 lines
2.9 KiB
Python
Raw Normal View History

2022-02-26 01:09:27 +08:00
2022-03-09 12:36:24 +08:00
from traceback import print_exc
2022-02-26 01:09:27 +08:00
from natpmp import NATPMP as pmp
2022-03-09 12:36:24 +08:00
import upnpy
2022-02-26 01:09:27 +08:00
from requests import get
from .background import Background
class AcrossNat(object):
def __init__(self):
self.external_ip = None
self.upnp = None
self.pmp_supported = True
self.upnp_supported = True
self.init_pmp()
2022-03-09 12:36:24 +08:00
self.init_upnp()
2022-02-26 01:09:27 +08:00
2022-03-09 12:36:24 +08:00
def init_upnp(self):
try:
upnp = upnpy.UPnP()
igd = upnp.discover()[0]
s_names = [ n for n in igd.services.keys() if n.startswith('WANPPPConn') ]
self.upnp = igd.services[s_names[0]]
except Exception as e:
print(e)
print_exc()
self.upnp_supported = False
2022-02-26 01:09:27 +08:00
def init_pmp(self):
try:
self.external_ip = pmp.get_public_address()
except pmp.NATPMPUnsupportedError:
self.pmp_supported = False
2022-03-09 12:36:24 +08:00
def get_external_ip(self):
2022-02-26 01:09:27 +08:00
if self.pmp_supported:
2022-02-28 12:06:25 +08:00
self.external_ip = pmp.get_public_address()
return self.external_ip
2022-02-26 01:09:27 +08:00
if self.upnp_supported:
2022-03-09 12:36:24 +08:00
x = self.upnp.GetExternalIPAddress()
return x['NewExternalIPAddress']
2022-02-26 01:09:27 +08:00
try:
return get('https://api.ipify.org').text
except:
return get('https://ipapi.co/ip/').text
2022-03-09 12:36:24 +08:00
def upnp_check_external_port(self, eport, protocol='TCP'):
try:
self.upnp.GetSpecificPortMappingEntry(NewExternalPort=eport,
NewProtocol=protocol,
NewRemoteHost='')
return True
except:
return False
2022-02-28 14:01:18 +08:00
2022-03-09 12:36:24 +08:00
def upnp_map_port(self, inner_port,
protocol='TCP', from_port=40003,
ip=None, desc='test'):
2022-02-28 14:01:18 +08:00
2022-03-09 12:36:24 +08:00
protocol = protocol.upper()
2022-02-26 01:09:27 +08:00
external_port = from_port
while external_port < 52333:
2022-03-09 12:51:07 +08:00
if self.upnp_check_external_port(external_port,
protocol=protocol):
2022-03-09 12:36:24 +08:00
external_port += 1
continue
2022-03-09 13:12:12 +08:00
try:
self.upnp.AddPortMapping(NewRemoteHost='',
NewExternalPort=external_port,
NewProtocol=protocol,
NewInternalPort=inner_port,
NewInternalClient=ip,
NewEnabled=1,
NewPortMappingDescription=desc,
NewLeaseDuration=0
)
return external_port
except:
return None
2022-02-26 01:09:27 +08:00
return None
2022-03-09 12:36:24 +08:00
def is_port_mapped(self, external_port, protocol='TCP'):
2022-02-26 01:09:27 +08:00
protocol = protocol.upper()
if self.upnp_supported:
2022-03-09 12:36:24 +08:00
return self.upnp_map_port_check(external_port,
protocol=protocol)
2022-02-26 01:09:27 +08:00
raise Exception('not implemented')
2022-03-09 12:36:24 +08:00
def port_unmap(self, external_port, protocol='TCP'):
2022-02-26 01:09:27 +08:00
protocol = protocol.upper()
if self.upnp_supported:
2022-03-09 12:36:24 +08:00
self.upnp.delete_port_mapping(external_port, protocol)
2022-02-26 01:09:27 +08:00
raise Exception('not implemented')
2022-02-28 12:06:25 +08:00
def pmp_map_port(self, inner_port, protocol='TCP', from_port=40003):
if protocol.upper() == 'TCP':
x = pmp.map_tcp_port(from_port, inner_port,
lifetime=999999999)
return x.public_port
x = pmp.map_udp_port(from_port, inner_port,
lifetime=999999999)
return x.public_port
2022-02-26 01:09:27 +08:00
2022-03-09 12:36:24 +08:00
def map_port(self, inner_port, protocol='tcp', from_port=40003, lan_ip=None, desc=None):
2022-02-28 12:06:25 +08:00
if self.pmp_supported:
return self.pmp_map_port(inner_port, protocol=protocol)
2022-02-26 01:09:27 +08:00
2022-03-09 12:36:24 +08:00
return self.upnp_map_port( inner_port, protocol=protocol, ip=lan_ip, desc=desc)
2022-02-26 01:09:27 +08:00