Added proxy and tests for proxy

This commit is contained in:
Josiah Baldwin
2024-12-09 16:41:59 -08:00
parent 20843dbea7
commit 1adaccabc0
10 changed files with 9406 additions and 21 deletions

Binary file not shown.

View File

@@ -46,6 +46,7 @@ install_requires =
importlib-metadata
cryptography>=43.0.3
websockets>=13.1
python-socks[asyncio]
[options.packages.find]

View File

@@ -8,6 +8,8 @@ import json
import datetime
import io
import ssl
import urllib
from python_socks.async_.asyncio import Proxy
from . import constants
from . import exceptions
from . import util
@@ -122,16 +124,17 @@ class Session(object):
ssl_context.verify_mode = ssl.CERT_NONE
options = { "ssl": ssl_context }
# Setup the HTTP proxy if needed
# if (self._proxy != None):
# options.agent = new https_proxy_agent(urllib.parse(self._proxy))
headers = websockets.datastructures.Headers()
if (self._password):
token = self._token if self._token else b""
headers['x-meshauth'] = (base64.b64encode(self._user.encode()) + b',' + base64.b64encode(self._password.encode()) + token).decode()
if self._proxy:
proxy = Proxy.from_url(self._proxy)
parsed = urllib.parse.urlparse(self.url)
options["sock"] = await proxy.connect(dest_host=parsed.hostname, dest_port=parsed.port)
options["additional_headers"] = headers
async for websocket in websockets.asyncio.client.connect(self.url, process_exception=util._process_websocket_exception, **options):
self.alive = True

View File

@@ -4,6 +4,8 @@ import websockets.asyncio
import websockets.asyncio.client
import asyncio
import ssl
from python_socks.async_.asyncio import Proxy
import urllib
from . import exceptions
from . import util
from . import constants
@@ -52,10 +54,6 @@ class Tunnel(object):
ssl_context.verify_mode = ssl.CERT_NONE
options = { "ssl": ssl_context }
# Setup the HTTP proxy if needed
# if (self._session._proxy != None):
# options.agent = new https_proxy_agent(urllib.parse(this._proxy))
if (self.node_id.split('/') != 3) and (self._session._currentDomain is not None):
self.node_id = f"node/{self._session._currentDomain}/{self.node_id}"
@@ -72,13 +70,11 @@ class Tunnel(object):
self.url = self._session.url.replace('/control.ashx', '/meshrelay.ashx?browser=1&p=' + str(self._protocol) + '&nodeid=' + self.node_id + '&id=' + self._tunnel_id + '&auth=' + authcookie["cookie"])
# headers = websockets.datastructures.Headers()
if self._session._proxy:
proxy = Proxy.from_url(self._session._proxy)
parsed = urllib.parse.urlparse(self.url)
options["sock"] = await proxy.connect(dest_host=parsed.hostname, dest_port=parsed.port)
# if (self._password):
# token = self._token if self._token else b""
# headers['x-meshauth'] = (base64.b64encode(self._user.encode()) + b',' + base64.b64encode(self._password.encode()) + token).decode()
# options["additional_headers"] = headers
async for websocket in websockets.asyncio.client.connect(self.url, process_exception=util._process_websocket_exception, **options):
self.alive = True
self._socket_open.set()

View File

@@ -54,13 +54,16 @@ class TestEnvironment(object):
self._subp = None
self.mcurl = "wss://localhost:8086"
self.clienturl = "http://localhost:5000"
self._dockerurl = "host.docker.internal:8086"
self.dockerurl = "host.docker.internal:8086"
self.proxyurl = "http://localhost:3128"
def __enter__(self):
global _docker_process
if _docker_process is not None:
self._subp = _docker_process
return self
# Destroy the env in case it wasn't killed correctly last time.
subprocess.check_call(["docker", "compose", "down"], stdout=subprocess.DEVNULL, cwd=thisdir)
self._subp = _docker_process = subprocess.Popen(["docker", "compose", "up", "--build", "--force-recreate", "--no-deps"], stdout=subprocess.DEVNULL, cwd=thisdir)
timeout = 30
start = time.time()
@@ -88,7 +91,7 @@ class TestEnvironment(object):
pass
def create_agent(self, meshid):
return Agent(meshid, self.mcurl, self.clienturl, self._dockerurl)
return Agent(meshid, self.mcurl, self.clienturl, self.dockerurl)
def _kill_docker_process():
if _docker_process is not None:

View File

@@ -19,9 +19,9 @@ services:
# # mongodb data-directory - A must for data persistence
# - ./meshcentral/mongodb_data:/data/db
networks:
- meshctrl
- meshctrl
extra_hosts:
- "host.docker.internal:host-gateway"
- "host.docker.internal:host-gateway"
meshcentral:
restart: always
@@ -49,4 +49,21 @@ services:
healthcheck:
test: curl -k --fail https://localhost:443/ || exit 1
interval: 5s
timeout: 120s
timeout: 120s
squid:
image: ubuntu/squid:latest
restart: unless-stopped
container_name: meshctrl-squid
ports:
- 3128:3128
networks:
- meshctrl
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./config/squid/conf.d:/etc/squid/conf.d
- ./config/squid/squid.conf:/etc/squid/squid.conf

View File

@@ -0,0 +1,11 @@
# Logs are managed by logrotate on Debian
logfile_rotate 0
acl all src all
acl Safe_ports port 8086
acl SSS_ports port 8086
http_access allow all
debug_options ALL,0 85,2 88,2
# Set max_filedescriptors to avoid using system's RLIMIT_NOFILE. See LP: #1978272
max_filedescriptors 1024

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ import io
import random
async def test_commands(env):
async with meshctrl.Session(env.mcurl, user="admin", password=env.users["admin"], ignore_ssl=True) as admin_session:
async with meshctrl.Session("wss://" + env.dockerurl, user="admin", password=env.users["admin"], ignore_ssl=True, proxy=env.proxyurl) as admin_session:
mesh = await admin_session.add_device_group("test", description="This is a test group", amtonly=False, features=0, consent=0, timeout=10)
try:
with env.create_agent(mesh.short_meshid) as agent:
@@ -53,7 +53,7 @@ async def test_commands(env):
assert (await admin_session.remove_device_group(mesh.meshid, timeout=10)), "Failed to remove device group"
async def test_upload_download(env):
async with meshctrl.Session(env.mcurl, user="admin", password=env.users["admin"], ignore_ssl=True) as admin_session:
async with meshctrl.Session("wss://" + env.dockerurl, user="admin", password=env.users["admin"], ignore_ssl=True, proxy=env.proxyurl) as admin_session:
mesh = await admin_session.add_device_group("test", description="This is a test group", amtonly=False, features=0, consent=0, timeout=10)
try:
with env.create_agent(mesh.short_meshid) as agent:

View File

@@ -25,6 +25,10 @@ async def test_sanity(env):
print("\ninfo server_info: {}\n".format(await s.server_info()))
pass
async def test_proxy(env):
async with meshctrl.Session("wss://" + env.dockerurl, user="unprivileged", password=env.users["unprivileged"], ignore_ssl=True, proxy=env.proxyurl) as s:
pass
async def test_ssl(env):
try:
async with meshctrl.Session(env.mcurl, user="unprivileged", password=env.users["unprivileged"], ignore_ssl=False) as s: