forked from netbox-community/netbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for socks connection to Git backend (netbox-community#17640)
* Add support for socks connection to Git backend * cleanup socks detection * add documentation for installing python_socks * dont need lower() * cleanup * refactor Socks to utilities * fix imports * fix missing comma * Update docs/features/synchronized-data.md Co-authored-by: Jeremy Stretch <[email protected]> * review feedback * Update docs/features/synchronized-data.md Co-authored-by: Jeremy Stretch <[email protected]> * review changes --------- Co-authored-by: Jeremy Stretch <[email protected]>
- Loading branch information
1 parent
d9028f9
commit 92d8aa5
Showing
4 changed files
with
125 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import logging | ||
|
||
from urllib.parse import urlparse | ||
from urllib3 import PoolManager, HTTPConnectionPool, HTTPSConnectionPool | ||
from urllib3.connection import HTTPConnection, HTTPSConnection | ||
from .constants import HTTP_PROXY_SOCK_RDNS_SCHEMAS | ||
|
||
|
||
logger = logging.getLogger('netbox.utilities') | ||
|
||
|
||
class ProxyHTTPConnection(HTTPConnection): | ||
""" | ||
A Proxy connection class that uses a SOCK proxy - used to create | ||
a urllib3 PoolManager that routes connections via the proxy. | ||
This is for an HTTP (not HTTPS) connection | ||
""" | ||
use_rdns = False | ||
|
||
def __init__(self, *args, **kwargs): | ||
socks_options = kwargs.pop('_socks_options') | ||
self._proxy_url = socks_options['proxy_url'] | ||
super().__init__(*args, **kwargs) | ||
|
||
def _new_conn(self): | ||
try: | ||
from python_socks.sync import Proxy | ||
except ModuleNotFoundError as e: | ||
logger.info("Configuring an HTTP proxy using SOCKS requires the python_socks library. Check that it has been installed.") | ||
raise e | ||
|
||
proxy = Proxy.from_url(self._proxy_url, rdns=self.use_rdns) | ||
return proxy.connect( | ||
dest_host=self.host, | ||
dest_port=self.port, | ||
timeout=self.timeout | ||
) | ||
|
||
|
||
class ProxyHTTPSConnection(ProxyHTTPConnection, HTTPSConnection): | ||
""" | ||
A Proxy connection class for an HTTPS (not HTTP) connection. | ||
""" | ||
pass | ||
|
||
|
||
class RdnsProxyHTTPConnection(ProxyHTTPConnection): | ||
""" | ||
A Proxy connection class for an HTTP remote-dns connection. | ||
I.E. socks4a, socks4h, socks5a, socks5h | ||
""" | ||
use_rdns = True | ||
|
||
|
||
class RdnsProxyHTTPSConnection(ProxyHTTPSConnection): | ||
""" | ||
A Proxy connection class for an HTTPS remote-dns connection. | ||
I.E. socks4a, socks4h, socks5a, socks5h | ||
""" | ||
use_rdns = True | ||
|
||
|
||
class ProxyHTTPConnectionPool(HTTPConnectionPool): | ||
ConnectionCls = ProxyHTTPConnection | ||
|
||
|
||
class ProxyHTTPSConnectionPool(HTTPSConnectionPool): | ||
ConnectionCls = ProxyHTTPSConnection | ||
|
||
|
||
class RdnsProxyHTTPConnectionPool(HTTPConnectionPool): | ||
ConnectionCls = RdnsProxyHTTPConnection | ||
|
||
|
||
class RdnsProxyHTTPSConnectionPool(HTTPSConnectionPool): | ||
ConnectionCls = RdnsProxyHTTPSConnection | ||
|
||
|
||
class ProxyPoolManager(PoolManager): | ||
def __init__(self, proxy_url, timeout=5, num_pools=10, headers=None, **connection_pool_kw): | ||
# python_socks uses rdns param to denote remote DNS parsing and | ||
# doesn't accept the 'h' or 'a' in the proxy URL | ||
if use_rdns := urlparse(proxy_url).scheme in HTTP_PROXY_SOCK_RDNS_SCHEMAS: | ||
proxy_url = proxy_url.replace('socks5h:', 'socks5:').replace('socks5a:', 'socks5:') | ||
proxy_url = proxy_url.replace('socks4h:', 'socks4:').replace('socks4a:', 'socks4:') | ||
|
||
connection_pool_kw['_socks_options'] = {'proxy_url': proxy_url} | ||
connection_pool_kw['timeout'] = timeout | ||
|
||
super().__init__(num_pools, headers, **connection_pool_kw) | ||
|
||
if use_rdns: | ||
self.pool_classes_by_scheme = { | ||
'http': RdnsProxyHTTPConnectionPool, | ||
'https': RdnsProxyHTTPSConnectionPool, | ||
} | ||
else: | ||
self.pool_classes_by_scheme = { | ||
'http': ProxyHTTPConnectionPool, | ||
'https': ProxyHTTPSConnectionPool, | ||
} |