| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 """ | 2 """ |
| 3 Copyright 2016 Google Inc. All Rights Reserved. | 3 Copyright 2016 Google Inc. All Rights Reserved. |
| 4 | 4 |
| 5 Licensed under the Apache License, Version 2.0 (the "License"); | 5 Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 you may not use this file except in compliance with the License. | 6 you may not use this file except in compliance with the License. |
| 7 You may obtain a copy of the License at | 7 You may obtain a copy of the License at |
| 8 | 8 |
| 9 http://www.apache.org/licenses/LICENSE-2.0 | 9 http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | 10 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 self.available_bytes = .0 | 150 self.available_bytes = .0 |
| 151 self.last_tick = now | 151 self.last_tick = now |
| 152 | 152 |
| 153 return processed_messages | 153 return processed_messages |
| 154 | 154 |
| 155 | 155 |
| 156 ################################################################################
######################################## | 156 ################################################################################
######################################## |
| 157 # Threaded DNS resolver | 157 # Threaded DNS resolver |
| 158 ################################################################################
######################################## | 158 ################################################################################
######################################## |
| 159 class AsyncDNS(threading.Thread): | 159 class AsyncDNS(threading.Thread): |
| 160 def __init__(self, client_id, hostname, port, result_pipe): | 160 def __init__(self, client_id, hostname, port, is_localhost, result_pipe): |
| 161 threading.Thread.__init__(self) | 161 threading.Thread.__init__(self) |
| 162 self.hostname = hostname | 162 self.hostname = hostname |
| 163 self.port = port | 163 self.port = port |
| 164 self.client_id = client_id | 164 self.client_id = client_id |
| 165 self.is_localhost = is_localhost |
| 165 self.result_pipe = result_pipe | 166 self.result_pipe = result_pipe |
| 166 | 167 |
| 167 def run(self): | 168 def run(self): |
| 168 global lock, background_activity_count | 169 global lock, background_activity_count |
| 169 try: | 170 try: |
| 170 logging.debug('[{0:d}] AsyncDNS - calling getaddrinfo for {1}:{2:d}'.forma
t(self.client_id, self.hostname, self.port)) | 171 logging.debug('[{0:d}] AsyncDNS - calling getaddrinfo for {1}:{2:d}'.forma
t(self.client_id, self.hostname, self.port)) |
| 171 addresses = socket.getaddrinfo(self.hostname, self.port) | 172 addresses = socket.getaddrinfo(self.hostname, self.port) |
| 172 logging.info('[{0:d}] Resolving {1}:{2:d} Completed'.format(self.client_id
, self.hostname, self.port)) | 173 logging.info('[{0:d}] Resolving {1}:{2:d} Completed'.format(self.client_id
, self.hostname, self.port)) |
| 173 except: | 174 except: |
| 174 addresses = () | 175 addresses = () |
| 175 logging.info('[{0:d}] Resolving {1}:{2:d} Failed'.format(self.client_id, s
elf.hostname, self.port)) | 176 logging.info('[{0:d}] Resolving {1}:{2:d} Failed'.format(self.client_id, s
elf.hostname, self.port)) |
| 176 message = {'message': 'resolved', 'connection': self.client_id, 'addresses':
addresses} | 177 message = {'message': 'resolved', 'connection': self.client_id, 'addresses':
addresses, 'localhost': self.is_localhost} |
| 177 self.result_pipe.SendMessage(message, False) | 178 self.result_pipe.SendMessage(message, False) |
| 178 lock.acquire() | 179 lock.acquire() |
| 179 if background_activity_count > 0: | 180 if background_activity_count > 0: |
| 180 background_activity_count -= 1 | 181 background_activity_count -= 1 |
| 181 lock.release() | 182 lock.release() |
| 182 # open and close a local socket which will interrupt the long polling loop t
o process the message | 183 # open and close a local socket which will interrupt the long polling loop t
o process the message |
| 183 s = socket.socket() | 184 s = socket.socket() |
| 184 s.connect((server.ipaddr, server.port)) | 185 s.connect((server.ipaddr, server.port)) |
| 185 s.close() | 186 s.close() |
| 186 | 187 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 200 asyncore.dispatcher.__init__(self) | 201 asyncore.dispatcher.__init__(self) |
| 201 self.client_id = client_id | 202 self.client_id = client_id |
| 202 self.state = self.STATE_IDLE | 203 self.state = self.STATE_IDLE |
| 203 self.buffer = '' | 204 self.buffer = '' |
| 204 self.addr = None | 205 self.addr = None |
| 205 self.dns_thread = None | 206 self.dns_thread = None |
| 206 self.hostname = None | 207 self.hostname = None |
| 207 self.port = None | 208 self.port = None |
| 208 self.needs_config = True | 209 self.needs_config = True |
| 209 self.needs_close = False | 210 self.needs_close = False |
| 210 self.is_localhost = False | |
| 211 self.did_resolve = False | 211 self.did_resolve = False |
| 212 | 212 |
| 213 def SendMessage(self, type, message): | 213 def SendMessage(self, type, message): |
| 214 message['message'] = type | 214 message['message'] = type |
| 215 message['connection'] = self.client_id | 215 message['connection'] = self.client_id |
| 216 in_pipe.SendMessage(message) | 216 in_pipe.SendMessage(message) |
| 217 | 217 |
| 218 def handle_message(self, message): | 218 def handle_message(self, message): |
| 219 if message['message'] == 'data' and 'data' in message and len(message['data'
]): | 219 if message['message'] == 'data' and 'data' in message and len(message['data'
]): |
| 220 self.buffer += message['data'] | 220 self.buffer += message['data'] |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 logging.debug('[{0:d}] TCP <= {1:d} byte(s)'.format(self.client_id,
len(data))) | 285 logging.debug('[{0:d}] TCP <= {1:d} byte(s)'.format(self.client_id,
len(data))) |
| 286 self.SendMessage('data', {'data': data}) | 286 self.SendMessage('data', {'data': data}) |
| 287 else: | 287 else: |
| 288 return | 288 return |
| 289 except: | 289 except: |
| 290 pass | 290 pass |
| 291 | 291 |
| 292 def HandleResolve(self, message): | 292 def HandleResolve(self, message): |
| 293 global in_pipe, map_localhost, lock, background_activity_count | 293 global in_pipe, map_localhost, lock, background_activity_count |
| 294 self.did_resolve = True | 294 self.did_resolve = True |
| 295 is_localhost = False |
| 295 if 'hostname' in message: | 296 if 'hostname' in message: |
| 296 self.hostname = message['hostname'] | 297 self.hostname = message['hostname'] |
| 297 self.port = 0 | 298 self.port = 0 |
| 298 if 'port' in message: | 299 if 'port' in message: |
| 299 self.port = message['port'] | 300 self.port = message['port'] |
| 300 logging.info('[{0:d}] Resolving {1}:{2:d}'.format(self.client_id, self.hostn
ame, self.port)) | 301 logging.info('[{0:d}] Resolving {1}:{2:d}'.format(self.client_id, self.hostn
ame, self.port)) |
| 301 if self.hostname == 'localhost': | 302 if self.hostname == 'localhost': |
| 302 self.hostname = '127.0.0.1' | 303 self.hostname = '127.0.0.1' |
| 303 if self.hostname == '127.0.0.1': | 304 if self.hostname == '127.0.0.1': |
| 304 logging.info('[{0:d}] Connection to localhost detected'.format(self.client
_id)) | 305 logging.info('[{0:d}] Connection to localhost detected'.format(self.client
_id)) |
| 305 self.is_localhost = True | 306 is_localhost = True |
| 306 if (dest_addresses is not None) and (not self.is_localhost or map_localhost)
: | 307 if (dest_addresses is not None) and (not is_localhost or map_localhost): |
| 307 logging.info('[{0:d}] Resolving {1}:{2:d} to mapped address {3}'.format(se
lf.client_id, self.hostname, self.port, dest_addresses)) | 308 logging.info('[{0:d}] Resolving {1}:{2:d} to mapped address {3}'.format(se
lf.client_id, self.hostname, self.port, dest_addresses)) |
| 308 self.SendMessage('resolved', {'addresses': dest_addresses}) | 309 self.SendMessage('resolved', {'addresses': dest_addresses, 'localhost': Fa
lse}) |
| 309 else: | 310 else: |
| 310 lock.acquire() | 311 lock.acquire() |
| 311 background_activity_count += 1 | 312 background_activity_count += 1 |
| 312 lock.release() | 313 lock.release() |
| 313 self.state = self.STATE_RESOLVING | 314 self.state = self.STATE_RESOLVING |
| 314 self.dns_thread = AsyncDNS(self.client_id, self.hostname, self.port, in_pi
pe) | 315 self.dns_thread = AsyncDNS(self.client_id, self.hostname, self.port, is_lo
calhost, in_pipe) |
| 315 self.dns_thread.start() | 316 self.dns_thread.start() |
| 316 | 317 |
| 317 def HandleConnect(self, message): | 318 def HandleConnect(self, message): |
| 318 global map_localhost | 319 global map_localhost |
| 319 if 'addresses' in message and len(message['addresses']): | 320 if 'addresses' in message and len(message['addresses']): |
| 320 self.state = self.STATE_CONNECTING | 321 self.state = self.STATE_CONNECTING |
| 321 if not self.did_resolve and message['addresses'][0] == '127.0.0.1': | 322 is_localhost = False |
| 323 if 'localhost' in message: |
| 324 is_localhost = message['localhost'] |
| 325 elif not self.did_resolve and message['addresses'][0] == '127.0.0.1': |
| 322 logging.info('[{0:d}] Connection to localhost detected'.format(self.clie
nt_id)) | 326 logging.info('[{0:d}] Connection to localhost detected'.format(self.clie
nt_id)) |
| 323 self.is_localhost = True | 327 is_localhost = True |
| 324 if (dest_addresses is not None) and (not self.is_localhost or map_localhos
t): | 328 if (dest_addresses is not None) and (not is_localhost or map_localhost): |
| 325 self.addr = dest_addresses[0] | 329 self.addr = dest_addresses[0] |
| 326 else: | 330 else: |
| 327 self.addr = message['addresses'][0] | 331 self.addr = message['addresses'][0] |
| 328 self.create_socket(self.addr[0], socket.SOCK_STREAM) | 332 self.create_socket(self.addr[0], socket.SOCK_STREAM) |
| 329 addr = self.addr[4][0] | 333 addr = self.addr[4][0] |
| 330 if not self.is_localhost or map_localhost: | 334 if not is_localhost or map_localhost: |
| 331 port = GetDestPort(message['port']) | 335 port = GetDestPort(message['port']) |
| 332 else: | 336 else: |
| 333 port = message['port'] | 337 port = message['port'] |
| 334 logging.info('[{0:d}] Connecting to {1}:{2:d}'.format(self.client_id, addr
, port)) | 338 logging.info('[{0:d}] Connecting to {1}:{2:d}'.format(self.client_id, addr
, port)) |
| 335 self.connect((addr, port)) | 339 self.connect((addr, port)) |
| 336 | 340 |
| 337 | 341 |
| 338 ################################################################################
######################################## | 342 ################################################################################
######################################## |
| 339 # Socks5 Server | 343 # Socks5 Server |
| 340 ################################################################################
######################################## | 344 ################################################################################
######################################## |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 for i in range(16): | 481 for i in range(16): |
| 478 self.ip += '{0:02x}'.format(ord(data[4 + i])) | 482 self.ip += '{0:02x}'.format(ord(data[4 + i])) |
| 479 if i % 2 and i < 15: | 483 if i % 2 and i < 15: |
| 480 self.ip += ':' | 484 self.ip += ':' |
| 481 if port_offset and connections[self.client_id]['server'] is not No
ne: | 485 if port_offset and connections[self.client_id]['server'] is not No
ne: |
| 482 self.port = 256 * ord(data[port_offset]) + ord(data[port_offset
+ 1]) | 486 self.port = 256 * ord(data[port_offset]) + ord(data[port_offset
+ 1]) |
| 483 if self.port: | 487 if self.port: |
| 484 if self.ip is None and self.hostname is not None: | 488 if self.ip is None and self.hostname is not None: |
| 485 if self.hostname in dns_cache: | 489 if self.hostname in dns_cache: |
| 486 self.state = self.STATE_CONNECTING | 490 self.state = self.STATE_CONNECTING |
| 487 self.addresses = dns_cache[self.hostname] | 491 cache_entry = dns_cache[self.hostname] |
| 488 self.SendMessage('connect', {'addresses': self.addresses,
'port': self.port}) | 492 self.addresses = cache_entry['addresses'] |
| 493 self.SendMessage('connect', {'addresses': self.addresses,
'port': self.port, 'localhost': cache_entry['localhost']}) |
| 489 else: | 494 else: |
| 490 self.state = self.STATE_RESOLVING | 495 self.state = self.STATE_RESOLVING |
| 491 self.SendMessage('resolve', {'hostname': self.hostname, 'p
ort': self.port}) | 496 self.SendMessage('resolve', {'hostname': self.hostname, 'p
ort': self.port}) |
| 492 elif self.ip is not None: | 497 elif self.ip is not None: |
| 493 self.state = self.STATE_CONNECTING | 498 self.state = self.STATE_CONNECTING |
| 494 logging.debug('[{0:d}] Socks Connect - calling getaddrinfo f
or {1}:{2:d}'.format(self.client_id, self.ip, self.port)) | 499 logging.debug('[{0:d}] Socks Connect - calling getaddrinfo f
or {1}:{2:d}'.format(self.client_id, self.ip, self.port)) |
| 495 self.addresses = socket.getaddrinfo(self.ip, self.port) | 500 self.addresses = socket.getaddrinfo(self.ip, self.port) |
| 496 self.SendMessage('connect', {'addresses': self.addresses, 'p
ort': self.port}) | 501 self.SendMessage('connect', {'addresses': self.addresses, 'p
ort': self.port}) |
| 497 else: | 502 else: |
| 498 return | 503 return |
| (...skipping 14 matching lines...) Expand all Loading... |
| 513 del connections[self.client_id] | 518 del connections[self.client_id] |
| 514 except: | 519 except: |
| 515 pass | 520 pass |
| 516 | 521 |
| 517 def HandleResolved(self, message): | 522 def HandleResolved(self, message): |
| 518 global dns_cache | 523 global dns_cache |
| 519 if self.state == self.STATE_RESOLVING: | 524 if self.state == self.STATE_RESOLVING: |
| 520 if 'addresses' in message and len(message['addresses']): | 525 if 'addresses' in message and len(message['addresses']): |
| 521 self.state = self.STATE_CONNECTING | 526 self.state = self.STATE_CONNECTING |
| 522 self.addresses = message['addresses'] | 527 self.addresses = message['addresses'] |
| 523 dns_cache[self.hostname] = self.addresses | 528 dns_cache[self.hostname] = {'addresses': self.addresses, 'localhost': me
ssage['localhost']} |
| 524 logging.debug('[{0:d}] Resolved {1}, Connecting'.format(self.client_id,
self.hostname)) | 529 logging.debug('[{0:d}] Resolved {1}, Connecting'.format(self.client_id,
self.hostname)) |
| 525 self.SendMessage('connect', {'addresses': self.addresses, 'port': self.p
ort}) | 530 self.SendMessage('connect', {'addresses': self.addresses, 'port': self.p
ort, 'localhost': message['localhost']}) |
| 526 else: | 531 else: |
| 527 # Send host unreachable error | 532 # Send host unreachable error |
| 528 self.state = self.STATE_ERROR | 533 self.state = self.STATE_ERROR |
| 529 self.buffer += chr(0x05) + chr(0x04) + self.requested_address | 534 self.buffer += chr(0x05) + chr(0x04) + self.requested_address |
| 530 self.handle_write() | 535 self.handle_write() |
| 531 | 536 |
| 532 def HandleConnected(self, message): | 537 def HandleConnected(self, message): |
| 533 if 'success' in message and self.state == self.STATE_CONNECTING: | 538 if 'success' in message and self.state == self.STATE_CONNECTING: |
| 534 response = chr(0x05) | 539 response = chr(0x05) |
| 535 if message['success']: | 540 if message['success']: |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 if src == '*': | 772 if src == '*': |
| 768 port_mappings['default'] = int(dest) | 773 port_mappings['default'] = int(dest) |
| 769 logging.debug("Default port mapped to port {0}".format(dest)) | 774 logging.debug("Default port mapped to port {0}".format(dest)) |
| 770 else: | 775 else: |
| 771 logging.debug("Port {0} mapped to port {1}".format(src, dest)) | 776 logging.debug("Port {0} mapped to port {1}".format(src, dest)) |
| 772 port_mappings[src] = int(dest) | 777 port_mappings[src] = int(dest) |
| 773 | 778 |
| 774 | 779 |
| 775 if '__main__' == __name__: | 780 if '__main__' == __name__: |
| 776 main() | 781 main() |
| OLD | NEW |