more work
This commit is contained in:
parent
0d6c39900b
commit
c2f6bc369c
5 changed files with 79 additions and 56 deletions
|
@ -26,6 +26,50 @@ import struct
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def inet_ntop(family, ipstr):
|
||||||
|
if family == socket.AF_INET:
|
||||||
|
return socket.inet_ntoa(ipstr)
|
||||||
|
elif family == socket.AF_INET6:
|
||||||
|
v6addr = ':'.join(('%02X%02X' % (ord(i), ord(j)))
|
||||||
|
for i, j in zip(ipstr[::2], ipstr[1::2]))
|
||||||
|
return v6addr
|
||||||
|
|
||||||
|
|
||||||
|
def inet_pton(family, addr):
|
||||||
|
if family == socket.AF_INET:
|
||||||
|
return socket.inet_aton(addr)
|
||||||
|
elif family == socket.AF_INET6:
|
||||||
|
if '.' in addr: # a v4 addr
|
||||||
|
v4addr = addr[addr.rindex(':') + 1:]
|
||||||
|
v4addr = socket.inet_aton(v4addr)
|
||||||
|
v4addr = map(lambda x: ('%02X' % ord(x)), v4addr)
|
||||||
|
v4addr.insert(2, ':')
|
||||||
|
newaddr = addr[:addr.rindex(':') + 1] + ''.join(v4addr)
|
||||||
|
return inet_pton(family, newaddr)
|
||||||
|
dbyts = [0] * 8 # 8 groups
|
||||||
|
grps = addr.split(':')
|
||||||
|
for i, v in enumerate(grps):
|
||||||
|
if v:
|
||||||
|
dbyts[i] = int(v, 16)
|
||||||
|
else:
|
||||||
|
for j, w in enumerate(grps[::-1]):
|
||||||
|
if w:
|
||||||
|
dbyts[7 - j] = int(w, 16)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
break
|
||||||
|
return ''.join((chr(i // 256) + chr(i % 256)) for i in dbyts)
|
||||||
|
else:
|
||||||
|
raise RuntimeError("What family?")
|
||||||
|
|
||||||
|
|
||||||
|
if not hasattr(socket, 'inet_pton'):
|
||||||
|
socket.inet_pton = inet_pton
|
||||||
|
|
||||||
|
if not hasattr(socket, 'inet_ntop'):
|
||||||
|
socket.inet_ntop = inet_ntop
|
||||||
|
|
||||||
|
|
||||||
def parse_header(data):
|
def parse_header(data):
|
||||||
addrtype = ord(data[0])
|
addrtype = ord(data[0])
|
||||||
dest_addr = None
|
dest_addr = None
|
||||||
|
@ -61,4 +105,4 @@ def parse_header(data):
|
||||||
logging.warn('unsupported addrtype %d, maybe wrong password' % addrtype)
|
logging.warn('unsupported addrtype %d, maybe wrong password' % addrtype)
|
||||||
if dest_addr is None:
|
if dest_addr is None:
|
||||||
return None
|
return None
|
||||||
return (addrtype, dest_addr, dest_port, header_length)
|
return addrtype, dest_addr, dest_port, header_length
|
||||||
|
|
|
@ -243,9 +243,12 @@ def main():
|
||||||
ThreadingTCPServer.address_family = addrs[0][0]
|
ThreadingTCPServer.address_family = addrs[0][0]
|
||||||
tcp_servers = []
|
tcp_servers = []
|
||||||
udp_servers = []
|
udp_servers = []
|
||||||
for port, key in config['port_password'].items():
|
for port, password in config['port_password'].items():
|
||||||
|
a_config = config.copy()
|
||||||
|
a_config['server_port'] = port
|
||||||
|
a_config['password'] = password
|
||||||
logging.info("starting server at %s:%d" %
|
logging.info("starting server at %s:%d" %
|
||||||
tuple(tcp_server.server_address[:2]))
|
(a_config['server'], port))
|
||||||
tcp_server = tcprelay.TCPRelay(config, False)
|
tcp_server = tcprelay.TCPRelay(config, False)
|
||||||
tcp_servers.append(tcp_server)
|
tcp_servers.append(tcp_server)
|
||||||
udp_server = udprelay.UDPRelay(config, False)
|
udp_server = udprelay.UDPRelay(config, False)
|
||||||
|
@ -257,11 +260,11 @@ def main():
|
||||||
for udp_server in udp_servers:
|
for udp_server in udp_servers:
|
||||||
udp_server.start()
|
udp_server.start()
|
||||||
|
|
||||||
if int(config_workers) > 1:
|
if int(config['workers']) > 1:
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
children = []
|
children = []
|
||||||
is_child = False
|
is_child = False
|
||||||
for i in xrange(0, int(config_workers)):
|
for i in xrange(0, int(config['workers'])):
|
||||||
r = os.fork()
|
r = os.fork()
|
||||||
if r == 0:
|
if r == 0:
|
||||||
logging.info('worker started')
|
logging.info('worker started')
|
||||||
|
|
|
@ -26,6 +26,7 @@ import socket
|
||||||
import logging
|
import logging
|
||||||
import encrypt
|
import encrypt
|
||||||
import errno
|
import errno
|
||||||
|
import threading
|
||||||
import eventloop
|
import eventloop
|
||||||
from common import parse_header
|
from common import parse_header
|
||||||
|
|
||||||
|
@ -121,8 +122,8 @@ class TCPRelayHandler(object):
|
||||||
# forward address to remote
|
# forward address to remote
|
||||||
self._data_to_write_to_remote.append(data[:header_length])
|
self._data_to_write_to_remote.append(data[:header_length])
|
||||||
self.write_all_to_sock('\x05\x00\x00\x01' +
|
self.write_all_to_sock('\x05\x00\x00\x01' +
|
||||||
'\x00\x00\x00\x00\x10\x10',
|
'\x00\x00\x00\x00\x10\x10',
|
||||||
self._local_sock)
|
self._local_sock)
|
||||||
else:
|
else:
|
||||||
remote_addr = self._config['server']
|
remote_addr = self._config['server']
|
||||||
remote_port = self._config['server_port']
|
remote_port = self._config['server_port']
|
||||||
|
@ -230,6 +231,7 @@ class TCPRelay(object):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._is_local = is_local
|
self._is_local = is_local
|
||||||
self._closed = False
|
self._closed = False
|
||||||
|
self._thread = None
|
||||||
self._fd_to_handlers = {}
|
self._fd_to_handlers = {}
|
||||||
|
|
||||||
if is_local:
|
if is_local:
|
||||||
|
@ -270,8 +272,8 @@ class TCPRelay(object):
|
||||||
if sock == self._server_socket:
|
if sock == self._server_socket:
|
||||||
try:
|
try:
|
||||||
conn = self._server_socket.accept()
|
conn = self._server_socket.accept()
|
||||||
TCPRelayHandler(self._eventloop, conn, self._config,
|
TCPRelayHandler(self._fd_to_handlers, self._eventloop,
|
||||||
self._is_local)
|
conn, self._config, self._is_local)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
error_no = eventloop.errno_from_exception(e)
|
error_no = eventloop.errno_from_exception(e)
|
||||||
if error_no in [errno.EAGAIN, errno.EINPROGRESS]:
|
if error_no in [errno.EAGAIN, errno.EINPROGRESS]:
|
||||||
|
@ -287,3 +289,19 @@ class TCPRelay(object):
|
||||||
if now - last_time > 5:
|
if now - last_time > 5:
|
||||||
# TODO sweep timeouts
|
# TODO sweep timeouts
|
||||||
last_time = now
|
last_time = now
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self._closed:
|
||||||
|
raise Exception('closed')
|
||||||
|
t = threading.Thread(target=self._run)
|
||||||
|
t.setName('UDPThread')
|
||||||
|
t.setDaemon(False)
|
||||||
|
t.start()
|
||||||
|
self._thread = t
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self._closed = True
|
||||||
|
self._server_socket.close()
|
||||||
|
|
||||||
|
def thread(self):
|
||||||
|
return self._thread
|
|
@ -101,10 +101,12 @@ class UDPRelay(object):
|
||||||
self._method = config['method']
|
self._method = config['method']
|
||||||
self._timeout = config['timeout']
|
self._timeout = config['timeout']
|
||||||
self._is_local = is_local
|
self._is_local = is_local
|
||||||
self._cache = lru_cache.LRUCache(timeout=timeout,
|
self._cache = lru_cache.LRUCache(timeout=config['timeout'],
|
||||||
close_callback=self._close_client)
|
close_callback=self._close_client)
|
||||||
self._client_fd_to_server_addr = lru_cache.LRUCache(timeout=timeout)
|
self._client_fd_to_server_addr = \
|
||||||
|
lru_cache.LRUCache(timeout=config['timeout'])
|
||||||
self._closed = False
|
self._closed = False
|
||||||
|
self._thread = None
|
||||||
|
|
||||||
addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
|
addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
|
||||||
socket.SOCK_DGRAM, socket.SOL_UDP)
|
socket.SOCK_DGRAM, socket.SOL_UDP)
|
||||||
|
@ -206,7 +208,7 @@ class UDPRelay(object):
|
||||||
return
|
return
|
||||||
# addrtype, dest_addr, dest_port, header_length = header_result
|
# addrtype, dest_addr, dest_port, header_length = header_result
|
||||||
response = '\x00\x00\x00' + data
|
response = '\x00\x00\x00' + data
|
||||||
client_addr = self._client_fd_to_server_addr.get(sock.fileno(), None)
|
client_addr = self._client_fd_to_server_addr.get(sock.fileno())
|
||||||
if client_addr:
|
if client_addr:
|
||||||
self._server_socket.sendto(response, client_addr)
|
self._server_socket.sendto(response, client_addr)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -22,53 +22,9 @@
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import socket
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
def inet_ntop(family, ipstr):
|
|
||||||
if family == socket.AF_INET:
|
|
||||||
return socket.inet_ntoa(ipstr)
|
|
||||||
elif family == socket.AF_INET6:
|
|
||||||
v6addr = ':'.join(('%02X%02X' % (ord(i), ord(j)))
|
|
||||||
for i, j in zip(ipstr[::2], ipstr[1::2]))
|
|
||||||
return v6addr
|
|
||||||
|
|
||||||
|
|
||||||
def inet_pton(family, addr):
|
|
||||||
if family == socket.AF_INET:
|
|
||||||
return socket.inet_aton(addr)
|
|
||||||
elif family == socket.AF_INET6:
|
|
||||||
if '.' in addr: # a v4 addr
|
|
||||||
v4addr = addr[addr.rindex(':') + 1:]
|
|
||||||
v4addr = socket.inet_aton(v4addr)
|
|
||||||
v4addr = map(lambda x: ('%02X' % ord(x)), v4addr)
|
|
||||||
v4addr.insert(2, ':')
|
|
||||||
newaddr = addr[:addr.rindex(':') + 1] + ''.join(v4addr)
|
|
||||||
return inet_pton(family, newaddr)
|
|
||||||
dbyts = [0] * 8 # 8 groups
|
|
||||||
grps = addr.split(':')
|
|
||||||
for i, v in enumerate(grps):
|
|
||||||
if v:
|
|
||||||
dbyts[i] = int(v, 16)
|
|
||||||
else:
|
|
||||||
for j, w in enumerate(grps[::-1]):
|
|
||||||
if w:
|
|
||||||
dbyts[7 - j] = int(w, 16)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
break
|
|
||||||
return ''.join((chr(i // 256) + chr(i % 256)) for i in dbyts)
|
|
||||||
else:
|
|
||||||
raise RuntimeError("What family?")
|
|
||||||
|
|
||||||
|
|
||||||
if not hasattr(socket, 'inet_pton'):
|
|
||||||
socket.inet_pton = inet_pton
|
|
||||||
|
|
||||||
if not hasattr(socket, 'inet_ntop'):
|
|
||||||
socket.inet_ntop = inet_ntop
|
|
||||||
|
|
||||||
def find_config():
|
def find_config():
|
||||||
config_path = 'config.json'
|
config_path = 'config.json'
|
||||||
if os.path.exists(config_path):
|
if os.path.exists(config_path):
|
||||||
|
|
Loading…
Add table
Reference in a new issue