A minimal implementation of proxy for outgoing connections using PySocks,

special arg --tor currently just sets host and port for the socks_proxy.
This commit is contained in:
Lee Miller 2023-03-28 07:01:29 +03:00
parent 9bb3038547
commit a13c1c0b1b
Signed by: lee.miller
GPG Key ID: 4F97A5EA88F4AB63
4 changed files with 76 additions and 4 deletions

View File

@ -5,6 +5,7 @@ import errno
import logging
import math
import random
import re
import select
import socket
import ssl
@ -78,7 +79,9 @@ class ConnectionBase(threading.Thread):
self.s.settimeout(0)
if not self.server:
if self.network == 'ip':
self.send_queue.put(message.Version(self.host, self.port))
self.send_queue.put(message.Version(
('127.0.0.1' if shared.socks_proxy else self.host),
self.port))
else:
self.send_queue.put(message.Version('127.0.0.1', 7656))
while True:
@ -517,4 +520,44 @@ class Bootstrapper(ConnectionBase):
self.send_queue.put(None)
class SocksConnection(Connection):
"""The socks proxied connection"""
def _connect(self):
peer_str = '{0.host_print}:{0.port}'.format(self)
logging.debug('Connecting to %s', peer_str)
import socks
try:
self.s = socks.create_connection(
(self.host, self.port), 30, None, socks.PROXY_TYPE_SOCKS5,
shared.socks_proxy[0], shared.socks_proxy[1], True,
None, None, None)
self.status = 'connected'
logging.debug('Established SOCKS connection to %s', peer_str)
except socket.timeout:
pass
except socks.GeneralProxyError as e:
e = e.socket_err
if isinstance(e, socket.timeout) or (
# general failure, unreachable, refused
not e.errno and re.match(r'^0x0[1,4,5].*', e.msg)
):
logcall = logging.debug
else:
logcall = logging.info
logcall('Connection to %s failed. Reason: %s', peer_str, e)
except OSError as e:
# unreachable, refused, no route
(logging.info if e.errno not in (0, 101, 111, 113)
else logging.debug)(
'Connection to %s failed. Reason: %s', peer_str, e)
except Exception:
logging.info(
'Connection to %s failed.', peer_str, exc_info=True)
if self.status != 'connected':
self.status = 'failed'
shared.connection = Connection

View File

@ -8,6 +8,11 @@ import os
import signal
import socket
try:
import socks
except ImportError:
socks = None
from . import i2p, shared
from .advertiser import Advertiser
from .manager import Manager
@ -52,6 +57,14 @@ def parse_arguments(): # pylint: disable=too-many-branches,too-many-statements
'--i2p-transient', action='store_true',
help='Generate new I2P destination on start')
if socks is not None:
parser.add_argument(
'--socks-proxy',
help='SOCKS proxy address in the form <HOST>:<PORT>')
parser.add_argument(
'--tor', action='store_true',
help='The SOCKS proxy is tor, use 127.0.0.1:9050 if not specified')
args = parser.parse_args()
if args.port:
shared.listening_port = args.port
@ -71,7 +84,8 @@ def parse_arguments(): # pylint: disable=too-many-branches,too-many-statements
if args.no_ip:
shared.ip_enabled = False
if args.trusted_peer:
if len(args.trusted_peer) > 50:
if len(args.trusted_peer
) > 50 and not args.trusted_peer.endswith('onion'):
# I2P
shared.trusted_peer = (args.trusted_peer.encode(), 'i2p')
else:
@ -99,6 +113,16 @@ def parse_arguments(): # pylint: disable=too-many-branches,too-many-statements
if args.i2p_transient:
shared.i2p_transient = True
if socks is None:
return
if args.tor:
shared.tor = True
if not args.socks_proxy:
shared.socks_proxy = ('127.0.0.1', 9050)
if args.socks_proxy:
addr = args.socks_proxy.split(':')
shared.socks_proxy = (addr[0], int(addr[1]))
def bootstrap_from_dns():
"""Addes addresses of bootstrap servers to core nodes"""

View File

@ -11,7 +11,7 @@ import threading
import time
from . import proofofwork, shared, structure
from .connection import Bootstrapper, Connection
from .connection import Bootstrapper, Connection, SocksConnection
from .i2p import I2PDialer
@ -174,7 +174,9 @@ class Manager(threading.Thread):
else:
continue
else:
connect((host, port))
connect(
(host, port),
Connection if not shared.socks_proxy else SocksConnection)
hosts.add(group)
shared.hosts = hosts

View File

@ -27,6 +27,9 @@ header_length = 24
i2p_dest_obj_type = 0x493250
i2p_dest_obj_version = 1
socks_proxy = None
tor = False
i2p_enabled = False
i2p_transient = False
i2p_sam_host = '127.0.0.1'