Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Implement file-based configuration of multiple servers
Browse files Browse the repository at this point in the history
  • Loading branch information
nosoop committed Nov 29, 2022
1 parent 2b38676 commit 83c77f2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 25 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,19 @@

A tool to replay / proxy data across sockets. Like a daemonized `socat` of sorts.

Currently a work in progress at this stage.
## Configuration

Create a TOML file with the following:

```
[[proxies]]
# service will listen on this socket for incoming connections
listen.host = '127.0.16.5'
listen.port = 50007
# service will pass data between incoming connections and this socket
forward.host = '127.0.16.5'
forward.port = 8080
# multiple [[proxies]] sections can be specified
```
50 changes: 27 additions & 23 deletions netnsplice/__main__.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
#!/usr/bin/python3

import argparse
import socket
import pathlib
import socketserver
import threading
import time
import tomli

from .config import AppConfig
from .proxy import ProxyStreamRequestHandlerFactory


def main():
# this is a temporary setup to avoid having hardcoded args in commit history
parser = argparse.ArgumentParser(description="Proxies data between addresses")
parser.add_argument("listen_host")
parser.add_argument("listen_port", type=int)

parser.add_argument("forward_host")
parser.add_argument("forward_port", type=int)
parser.add_argument("config", type=pathlib.Path)

args = parser.parse_args()

listen_addr = (args.listen_host, args.listen_port)
forward_addr = (args.forward_host, args.forward_port)

handler = ProxyStreamRequestHandlerFactory(socket.AF_INET, forward_addr)
with socketserver.ThreadingTCPServer(listen_addr, handler) as server:
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()

# allow clean interrupts
try:
while server_thread.is_alive():
server_thread.join(0.5)
except (KeyboardInterrupt, SystemExit):
pass
finally:
server.shutdown()
config = AppConfig.parse_obj(tomli.loads(args.config.read_text()))

servers = []
for proxy in config.proxies:
handler = ProxyStreamRequestHandlerFactory(proxy.forward.family, proxy.forward.address)
server = socketserver.ThreadingTCPServer(proxy.listen.address, handler)

thread = threading.Thread(target=server.serve_forever)
thread.start()

servers.append(server)

# allow clean interrupts
try:
while True:
time.sleep(0.5)
except (KeyboardInterrupt, SystemExit):
pass

# shutdown listeners
for server in servers:
server.shutdown()


if __name__ == "__main__":
Expand Down
26 changes: 26 additions & 0 deletions netnsplice/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/python3

import pydantic
import socket


class NetSocketConfig(pydantic.BaseModel):
host: str
port: int

@property
def address(self):
return (self.host, self.port)

@property
def family(self) -> socket.AddressFamily:
return socket.AF_INET


class ProxyConfig(pydantic.BaseModel):
listen: NetSocketConfig
forward: NetSocketConfig


class AppConfig(pydantic.BaseModel):
proxies: list[ProxyConfig]
5 changes: 4 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = netnsplice
version = 0.0.1
version = 0.1.0
author = nosoop
description = Relays content across nework or file sockets
long_description = file: README.md
Expand All @@ -15,3 +15,6 @@ classifiers =
[options]
packages = find:
python_requires = >= 3.7
install_requires =
tomli
pydantic>=1.10.0

0 comments on commit 83c77f2

Please sign in to comment.