2015-07-12 20:36:46 +02:00
|
|
|
import re
|
2019-03-15 21:06:59 +01:00
|
|
|
import urllib.request
|
|
|
|
import http.client
|
2015-07-12 20:36:46 +02:00
|
|
|
import logging
|
2019-03-15 21:06:59 +01:00
|
|
|
from urllib.parse import urlparse
|
2015-02-16 00:41:41 +01:00
|
|
|
from xml.dom.minidom import parseString
|
2017-01-11 16:43:39 +01:00
|
|
|
from xml.parsers.expat import ExpatError
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
from gevent import socket
|
2017-11-09 13:33:02 +01:00
|
|
|
import gevent
|
2015-07-12 20:36:46 +02:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
# Relevant UPnP spec:
|
|
|
|
# http://www.upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
# General TODOs:
|
|
|
|
# Handle 0 or >1 IGDs
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2019-03-15 23:31:13 +01:00
|
|
|
logger = logging.getLogger("Upnp")
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
class UpnpError(Exception):
|
|
|
|
pass
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
|
|
|
|
class IGDError(UpnpError):
|
|
|
|
"""
|
|
|
|
Signifies a problem with the IGD.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
REMOVE_WHITESPACE = re.compile(r'>\s*<')
|
|
|
|
|
|
|
|
|
|
|
|
def perform_m_search(local_ip):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Broadcast a UDP SSDP M-SEARCH packet and return response.
|
|
|
|
"""
|
|
|
|
search_target = "urn:schemas-upnp-org:device:InternetGatewayDevice:1"
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
ssdp_request = ''.join(
|
|
|
|
['M-SEARCH * HTTP/1.1\r\n',
|
|
|
|
'HOST: 239.255.255.250:1900\r\n',
|
|
|
|
'MAN: "ssdp:discover"\r\n',
|
|
|
|
'MX: 2\r\n',
|
|
|
|
'ST: {0}\r\n'.format(search_target),
|
|
|
|
'\r\n']
|
2019-03-15 23:32:05 +01:00
|
|
|
).encode("utf8")
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
2015-03-08 01:22:09 +01:00
|
|
|
|
2017-11-09 13:33:02 +01:00
|
|
|
sock.bind((local_ip, 0))
|
2015-03-08 01:22:09 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
sock.sendto(ssdp_request, ('239.255.255.250', 1900))
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if local_ip == "127.0.0.1":
|
|
|
|
sock.settimeout(1)
|
|
|
|
else:
|
|
|
|
sock.settimeout(5)
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
try:
|
2019-03-15 23:32:05 +01:00
|
|
|
return sock.recv(2048).decode("utf8")
|
2016-08-10 17:03:58 +02:00
|
|
|
except socket.error:
|
|
|
|
raise UpnpError("No reply from IGD using {} as IP".format(local_ip))
|
2016-10-03 19:26:06 +02:00
|
|
|
finally:
|
|
|
|
sock.close()
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _retrieve_location_from_ssdp(response):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Parse raw HTTP response to retrieve the UPnP location header
|
|
|
|
and return a ParseResult object.
|
|
|
|
"""
|
2016-08-10 17:03:58 +02:00
|
|
|
parsed_headers = re.findall(r'(?P<name>.*?): (?P<value>.*?)\r\n', response)
|
|
|
|
header_locations = [header[1]
|
|
|
|
for header in parsed_headers
|
|
|
|
if header[0].lower() == 'location']
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
if len(header_locations) < 1:
|
|
|
|
raise IGDError('IGD response does not contain a "location" header.')
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
return urlparse(header_locations[0])
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _retrieve_igd_profile(url):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Retrieve the device's UPnP profile.
|
|
|
|
"""
|
2016-08-10 17:03:58 +02:00
|
|
|
try:
|
2019-03-15 21:06:59 +01:00
|
|
|
return urllib.request.urlopen(url.geturl(), timeout=5).read().decode('utf-8')
|
2016-08-10 17:03:58 +02:00
|
|
|
except socket.error:
|
|
|
|
raise IGDError('IGD profile query timed out')
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
def _get_first_child_data(node):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Get the text value of the first child text node of a node.
|
|
|
|
"""
|
|
|
|
return node.childNodes[0].data
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _parse_igd_profile(profile_xml):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Traverse the profile xml DOM looking for either
|
|
|
|
WANIPConnection or WANPPPConnection and return
|
2016-08-10 17:03:58 +02:00
|
|
|
the 'controlURL' and the service xml schema.
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
2017-01-11 16:43:39 +01:00
|
|
|
try:
|
|
|
|
dom = parseString(profile_xml)
|
|
|
|
except ExpatError as e:
|
|
|
|
raise IGDError(
|
|
|
|
'Unable to parse IGD reply: {0} \n\n\n {1}'.format(profile_xml, e))
|
2015-07-12 20:36:46 +02:00
|
|
|
|
|
|
|
service_types = dom.getElementsByTagName('serviceType')
|
|
|
|
for service in service_types:
|
2016-08-10 17:03:58 +02:00
|
|
|
if _get_first_child_data(service).find('WANIPConnection') > 0 or \
|
|
|
|
_get_first_child_data(service).find('WANPPPConnection') > 0:
|
|
|
|
try:
|
|
|
|
control_url = _get_first_child_data(
|
|
|
|
service.parentNode.getElementsByTagName('controlURL')[0])
|
|
|
|
upnp_schema = _get_first_child_data(service).split(':')[-2]
|
|
|
|
return control_url, upnp_schema
|
|
|
|
except IndexError:
|
|
|
|
# Pass the error because any error here should raise the
|
|
|
|
# that's specified outside the for loop.
|
|
|
|
pass
|
|
|
|
raise IGDError(
|
|
|
|
'Could not find a control url or UPNP schema in IGD response.')
|
|
|
|
|
|
|
|
|
|
|
|
# add description
|
|
|
|
def _get_local_ips():
|
2019-11-25 14:40:52 +01:00
|
|
|
def method1():
|
|
|
|
try:
|
|
|
|
# get local ip using UDP and a broadcast address
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
|
|
# Not using <broadcast> because gevents getaddrinfo doesn't like that
|
|
|
|
# using port 1 as per hobbldygoop's comment about port 0 not working on osx:
|
|
|
|
# https://github.com/sirMackk/ZeroNet/commit/fdcd15cf8df0008a2070647d4d28ffedb503fba2#commitcomment-9863928
|
|
|
|
s.connect(('239.255.255.250', 1))
|
|
|
|
return [s.getsockname()[0]]
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def method2():
|
|
|
|
# Get ip by using UDP and a normal address (google dns ip)
|
|
|
|
try:
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
s.connect(('8.8.8.8', 0))
|
|
|
|
return [s.getsockname()[0]]
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def method3():
|
|
|
|
# Get ip by '' hostname . Not supported on all platforms.
|
|
|
|
try:
|
|
|
|
return socket.gethostbyname_ex('')[2]
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
threads = [
|
|
|
|
gevent.spawn(method1),
|
|
|
|
gevent.spawn(method2),
|
|
|
|
gevent.spawn(method3)
|
|
|
|
]
|
2016-08-10 17:03:58 +02:00
|
|
|
|
2019-11-25 14:40:52 +01:00
|
|
|
gevent.joinall(threads, timeout=5)
|
2015-02-16 00:41:41 +01:00
|
|
|
|
2019-11-25 14:40:52 +01:00
|
|
|
local_ips = []
|
|
|
|
for thread in threads:
|
|
|
|
if thread.value:
|
|
|
|
local_ips += thread.value
|
2016-08-10 17:03:58 +02:00
|
|
|
|
|
|
|
# Delete duplicates
|
|
|
|
local_ips = list(set(local_ips))
|
2017-11-17 18:09:02 +01:00
|
|
|
|
2019-11-27 03:02:18 +01:00
|
|
|
|
2017-11-17 18:09:02 +01:00
|
|
|
# Probably we looking for an ip starting with 192
|
|
|
|
local_ips = sorted(local_ips, key=lambda a: a.startswith("192"), reverse=True)
|
2016-08-10 17:03:58 +02:00
|
|
|
|
|
|
|
return local_ips
|
|
|
|
|
|
|
|
|
|
|
|
def _create_open_message(local_ip,
|
|
|
|
port,
|
|
|
|
description="UPnPPunch",
|
|
|
|
protocol="TCP",
|
2015-07-12 20:36:46 +02:00
|
|
|
upnp_schema='WANIPConnection'):
|
|
|
|
"""
|
|
|
|
Build a SOAP AddPortMapping message.
|
|
|
|
"""
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
soap_message = """<?xml version="1.0"?>
|
2015-02-16 00:41:41 +01:00
|
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
2015-07-12 20:36:46 +02:00
|
|
|
<s:Body>
|
|
|
|
<u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:{upnp_schema}:1">
|
|
|
|
<NewRemoteHost></NewRemoteHost>
|
|
|
|
<NewExternalPort>{port}</NewExternalPort>
|
|
|
|
<NewProtocol>{protocol}</NewProtocol>
|
|
|
|
<NewInternalPort>{port}</NewInternalPort>
|
|
|
|
<NewInternalClient>{host_ip}</NewInternalClient>
|
|
|
|
<NewEnabled>1</NewEnabled>
|
|
|
|
<NewPortMappingDescription>{description}</NewPortMappingDescription>
|
|
|
|
<NewLeaseDuration>0</NewLeaseDuration>
|
|
|
|
</u:AddPortMapping>
|
|
|
|
</s:Body>
|
2015-02-16 00:41:41 +01:00
|
|
|
</s:Envelope>""".format(port=port,
|
2015-07-12 20:36:46 +02:00
|
|
|
protocol=protocol,
|
|
|
|
host_ip=local_ip,
|
|
|
|
description=description,
|
|
|
|
upnp_schema=upnp_schema)
|
2016-08-10 17:03:58 +02:00
|
|
|
return (REMOVE_WHITESPACE.sub('><', soap_message), 'AddPortMapping')
|
|
|
|
|
|
|
|
|
|
|
|
def _create_close_message(local_ip,
|
|
|
|
port,
|
|
|
|
description=None,
|
|
|
|
protocol='TCP',
|
|
|
|
upnp_schema='WANIPConnection'):
|
|
|
|
soap_message = """<?xml version="1.0"?>
|
|
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
|
|
|
<s:Body>
|
|
|
|
<u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:{upnp_schema}:1">
|
|
|
|
<NewRemoteHost></NewRemoteHost>
|
|
|
|
<NewExternalPort>{port}</NewExternalPort>
|
|
|
|
<NewProtocol>{protocol}</NewProtocol>
|
|
|
|
</u:DeletePortMapping>
|
|
|
|
</s:Body>
|
|
|
|
</s:Envelope>""".format(port=port,
|
|
|
|
protocol=protocol,
|
|
|
|
upnp_schema=upnp_schema)
|
|
|
|
return (REMOVE_WHITESPACE.sub('><', soap_message), 'DeletePortMapping')
|
2015-02-24 14:02:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _parse_for_errors(soap_response):
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug(soap_response.status)
|
2016-08-10 17:03:58 +02:00
|
|
|
if soap_response.status >= 400:
|
2016-01-12 23:57:52 +01:00
|
|
|
response_data = soap_response.read()
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug(response_data)
|
2016-01-12 23:57:52 +01:00
|
|
|
try:
|
|
|
|
err_dom = parseString(response_data)
|
2016-08-10 17:03:58 +02:00
|
|
|
err_code = _get_first_child_data(err_dom.getElementsByTagName(
|
|
|
|
'errorCode')[0])
|
|
|
|
err_msg = _get_first_child_data(
|
2016-01-12 23:57:52 +01:00
|
|
|
err_dom.getElementsByTagName('errorDescription')[0]
|
|
|
|
)
|
2016-08-10 17:03:58 +02:00
|
|
|
except Exception as err:
|
|
|
|
raise IGDError(
|
|
|
|
'Unable to parse SOAP error: {0}. Got: "{1}"'.format(
|
|
|
|
err, response_data))
|
|
|
|
raise IGDError(
|
2015-07-12 20:36:46 +02:00
|
|
|
'SOAP request error: {0} - {1}'.format(err_code, err_msg)
|
|
|
|
)
|
2016-08-10 17:03:58 +02:00
|
|
|
return soap_response
|
2015-02-16 00:41:41 +01:00
|
|
|
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
def _send_soap_request(location, upnp_schema, control_path, soap_fn,
|
|
|
|
soap_message):
|
2015-07-12 20:36:46 +02:00
|
|
|
"""
|
|
|
|
Send out SOAP request to UPnP device and return a response.
|
|
|
|
"""
|
|
|
|
headers = {
|
|
|
|
'SOAPAction': (
|
|
|
|
'"urn:schemas-upnp-org:service:{schema}:'
|
2016-08-10 17:03:58 +02:00
|
|
|
'1#{fn_name}"'.format(schema=upnp_schema, fn_name=soap_fn)
|
2015-07-12 20:36:46 +02:00
|
|
|
),
|
|
|
|
'Content-Type': 'text/xml'
|
|
|
|
}
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug("Sending UPnP request to {0}:{1}...".format(
|
2016-08-10 17:03:58 +02:00
|
|
|
location.hostname, location.port))
|
2019-03-15 21:06:59 +01:00
|
|
|
conn = http.client.HTTPConnection(location.hostname, location.port)
|
2016-08-10 17:03:58 +02:00
|
|
|
conn.request('POST', control_path, soap_message, headers)
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
response = conn.getresponse()
|
|
|
|
conn.close()
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
return _parse_for_errors(response)
|
2015-02-24 14:02:05 +01:00
|
|
|
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
def _collect_idg_data(ip_addr):
|
|
|
|
idg_data = {}
|
|
|
|
idg_response = perform_m_search(ip_addr)
|
|
|
|
idg_data['location'] = _retrieve_location_from_ssdp(idg_response)
|
|
|
|
idg_data['control_path'], idg_data['upnp_schema'] = _parse_igd_profile(
|
|
|
|
_retrieve_igd_profile(idg_data['location']))
|
|
|
|
return idg_data
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2015-03-04 03:46:55 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
def _send_requests(messages, location, upnp_schema, control_path):
|
|
|
|
responses = [_send_soap_request(location, upnp_schema, control_path,
|
|
|
|
message_tup[1], message_tup[0])
|
|
|
|
for message_tup in messages]
|
2015-03-04 03:46:55 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
if all(rsp.status == 200 for rsp in responses):
|
|
|
|
return
|
|
|
|
raise UpnpError('Sending requests using UPnP failed.')
|
2015-02-24 14:02:05 +01:00
|
|
|
|
|
|
|
|
2017-01-11 16:43:39 +01:00
|
|
|
def _orchestrate_soap_request(ip, port, msg_fn, desc=None, protos=("TCP", "UDP")):
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug("Trying using local ip: %s" % ip)
|
2016-08-10 17:03:58 +02:00
|
|
|
idg_data = _collect_idg_data(ip)
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
soap_messages = [
|
|
|
|
msg_fn(ip, port, desc, proto, idg_data['upnp_schema'])
|
2016-10-02 14:39:03 +02:00
|
|
|
for proto in protos
|
2016-08-10 17:03:58 +02:00
|
|
|
]
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
_send_requests(soap_messages, **idg_data)
|
2015-02-24 14:02:05 +01:00
|
|
|
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
def _communicate_with_igd(port=15441,
|
|
|
|
desc="UpnpPunch",
|
|
|
|
retries=3,
|
2016-10-02 14:39:03 +02:00
|
|
|
fn=_create_open_message,
|
2017-01-11 16:43:39 +01:00
|
|
|
protos=("TCP", "UDP")):
|
2016-08-10 17:03:58 +02:00
|
|
|
"""
|
|
|
|
Manage sending a message generated by 'fn'.
|
|
|
|
"""
|
|
|
|
|
2017-11-09 13:33:02 +01:00
|
|
|
local_ips = _get_local_ips()
|
2016-08-10 17:03:58 +02:00
|
|
|
success = False
|
|
|
|
|
2017-11-09 13:33:02 +01:00
|
|
|
def job(local_ip):
|
|
|
|
for retry in range(retries):
|
|
|
|
try:
|
|
|
|
_orchestrate_soap_request(local_ip, port, fn, desc, protos)
|
|
|
|
return True
|
2017-11-17 18:08:45 +01:00
|
|
|
except Exception as e:
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug('Upnp request using "{0}" failed: {1}'.format(local_ip, e))
|
2017-11-09 13:33:02 +01:00
|
|
|
gevent.sleep(1)
|
|
|
|
return False
|
|
|
|
|
|
|
|
threads = []
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
for local_ip in local_ips:
|
2017-11-17 18:09:02 +01:00
|
|
|
job_thread = gevent.spawn(job, local_ip)
|
|
|
|
threads.append(job_thread)
|
2017-11-09 13:33:02 +01:00
|
|
|
gevent.sleep(0.1)
|
|
|
|
if any([thread.value for thread in threads]):
|
2016-08-10 17:03:58 +02:00
|
|
|
success = True
|
2016-09-29 15:24:46 +02:00
|
|
|
break
|
2017-11-09 13:33:02 +01:00
|
|
|
|
2020-12-21 21:44:57 +01:00
|
|
|
# Wait another 10sec for competition or any positive result
|
2017-11-09 13:33:02 +01:00
|
|
|
for _ in range(10):
|
2017-11-17 18:09:02 +01:00
|
|
|
all_done = all([thread.value is not None for thread in threads])
|
2017-11-09 13:33:02 +01:00
|
|
|
any_succeed = any([thread.value for thread in threads])
|
|
|
|
if all_done or any_succeed:
|
|
|
|
break
|
|
|
|
gevent.sleep(1)
|
|
|
|
|
|
|
|
if any([thread.value for thread in threads]):
|
|
|
|
success = True
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
if not success:
|
|
|
|
raise UpnpError(
|
|
|
|
'Failed to communicate with igd using port {0} on local machine after {1} tries.'.format(
|
|
|
|
port, retries))
|
|
|
|
|
2019-03-18 01:07:46 +01:00
|
|
|
return success
|
|
|
|
|
2016-08-10 17:03:58 +02:00
|
|
|
|
2017-01-11 16:43:39 +01:00
|
|
|
def ask_to_open_port(port=15441, desc="UpnpPunch", retries=3, protos=("TCP", "UDP")):
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug("Trying to open port %d." % port)
|
2019-03-18 01:07:46 +01:00
|
|
|
return _communicate_with_igd(port=port,
|
2016-08-10 17:03:58 +02:00
|
|
|
desc=desc,
|
|
|
|
retries=retries,
|
2016-10-02 14:39:03 +02:00
|
|
|
fn=_create_open_message,
|
|
|
|
protos=protos)
|
2015-02-24 14:02:05 +01:00
|
|
|
|
2015-03-08 01:22:09 +01:00
|
|
|
|
2017-01-11 16:43:39 +01:00
|
|
|
def ask_to_close_port(port=15441, desc="UpnpPunch", retries=3, protos=("TCP", "UDP")):
|
2019-03-15 23:31:13 +01:00
|
|
|
logger.debug("Trying to close port %d." % port)
|
2016-08-10 17:03:58 +02:00
|
|
|
# retries=1 because multiple successes cause 500 response and failure
|
2019-03-18 01:07:46 +01:00
|
|
|
return _communicate_with_igd(port=port,
|
2016-08-10 17:03:58 +02:00
|
|
|
desc=desc,
|
2017-11-09 13:33:02 +01:00
|
|
|
retries=retries,
|
2016-10-02 14:39:03 +02:00
|
|
|
fn=_create_close_message,
|
|
|
|
protos=protos)
|
2015-03-08 01:22:09 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2015-07-12 20:36:46 +02:00
|
|
|
from gevent import monkey
|
2017-11-09 13:33:02 +01:00
|
|
|
monkey.patch_all()
|
2019-03-15 23:31:13 +01:00
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
import time
|
2015-04-12 23:59:22 +02:00
|
|
|
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
s = time.time()
|
2019-03-15 21:06:59 +01:00
|
|
|
print("Opening port...")
|
2019-03-18 01:07:46 +01:00
|
|
|
print("Success:", ask_to_open_port(15443, "ZeroNet", protos=["TCP"]))
|
2019-03-15 21:06:59 +01:00
|
|
|
print("Done in", time.time() - s)
|
2016-10-02 14:39:03 +02:00
|
|
|
|
2019-11-27 03:02:18 +01:00
|
|
|
|
2019-03-15 21:06:59 +01:00
|
|
|
print("Closing port...")
|
2019-03-18 01:07:46 +01:00
|
|
|
print("Success:", ask_to_close_port(15443, "ZeroNet", protos=["TCP"]))
|
2019-03-15 21:06:59 +01:00
|
|
|
print("Done in", time.time() - s)
|
2019-11-27 03:02:18 +01:00
|
|
|
|