Merge branch '5-create-sam-server-tunnels-in-trans-proxy' into 'master'

Resolve "Create SAM server tunnels in trans-proxy"

Closes #5

See merge request NamingThingsIsHard/privacy/i2p-docker-proxy!4
This commit is contained in:
2021-01-06 21:46:35 +00:00
7 changed files with 157 additions and 4 deletions

View File

@ -19,6 +19,12 @@ iptables -t nat -A OUTPUT -o eth0 \
-p tcp --dport $PROXY_SAM_PORT \
-j ACCEPT
# Allow existing connections e.g for servers
iptables -t nat -A OUTPUT -o eth0 \
-m state \
--state RELATED,ESTABLISHED \
-j ACCEPT
# Redirect all other traffic on eth0 to trans-proxy
iptables -t nat -A OUTPUT -o eth0 \
-p tcp \
@ -37,5 +43,5 @@ ulogd -d
tcpdump -i any -w /mount/tcp.dmp &
export PYTHONPATH=/opt/bin
python3 /opt/bin/trans_proxy/cli.py \
python3 -m trans_proxy.cli \
--verbose

View File

@ -24,17 +24,22 @@ from i2plib import sam
from trans_proxy import fake_dns
from trans_proxy.process import AsyncProcess
from trans_proxy.servers import start_client_tcp_tunnel
from trans_proxy.servers.client import start_client_tcp_tunnel
from trans_proxy.servers.server import start_server_tcp_tunnel
ENV_PORT = "PROXY_PORT"
ENV_SAM_HOST = "PROXY_SAM_HOST"
ENV_SAM_PORT = "PROXY_SAM_PORT"
ENV_DNS_PORT = "PROXY_DNS_PORT"
ENV_SERVER_ACTIVE = "PROXY_SERVER_ACTIVE"
ENV_SERVER_PORT = "PROXY_SERVER_PORT"
ENV_PRIV_KEY = "PROXY_PRIV_KEY"
logger = logging.getLogger("trans_proxy.cli")
def main():
# TODO: Write helper formatter that prints default values and env var names
parser = argparse.ArgumentParser(
description="Forwards packets to an I2P instance and handles DNS requests"
)
@ -54,6 +59,14 @@ def main():
"--sam-port",
type=int,
default=os.environ.get(ENV_SAM_PORT, sam.DEFAULT_ADDRESS[1]))
# TODO: provide option to read this from a file (useful for docker secrets)
parser.add_argument(
"--priv-key",
help="Your private key in base64."
" It is generated by SAM automatically if none is provided."
" Reuse the generated one to have a stable address on the I2P network",
default=os.environ.get(ENV_PRIV_KEY)
)
dns_group = parser.add_argument_group('dns')
dns_group.add_argument(
@ -61,6 +74,17 @@ def main():
type=int,
default=os.environ.get(ENV_DNS_PORT, 1053))
server_group = parser.add_argument_group('server')
server_group.add_argument(
"--server",
action="store_true",
)
server_group.add_argument(
"--server-port",
type=int,
help="The port your app is listening to",
default=os.environ.get(ENV_SERVER_PORT, 80))
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
@ -85,6 +109,18 @@ def main():
}
)
]
if args.server or os.getenv(ENV_SERVER_ACTIVE):
processes.append(AsyncProcess(
target=start_server_tcp_tunnel,
kwargs={
"sam_host": args.sam_host,
"sam_port": args.sam_port,
"target_port": args.server_port,
"priv_key": args.priv_key,
}
))
exec_processes(processes)

View File

@ -0,0 +1,18 @@
# i2p-docker-proxy
# Copyright (C) 2019 LoveIsGrief
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
SESSION_NAME = "trans-proxy-sessions"

View File

@ -22,7 +22,7 @@ import i2plib
from trans_proxy.utils import get_original_ip
SESSION_NAME = "trans-proxy-sessions"
SESSION_NAME = "trans-proxy-session_client"
async def start_client_tcp_tunnel(
sam_host,

View File

@ -0,0 +1,73 @@
# i2p-docker-proxy
# Copyright (C) 2019 LoveIsGrief
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
import logging
import i2plib
from i2plib import Destination
from trans_proxy.types import Base64
SESSION_NAME = "trans-proxy-session_server"
async def start_server_tcp_tunnel(
sam_host: str,
sam_port: int,
target_port: int,
priv_key: Base64 = None,
):
"""
Starts a server tunnel that accepts requests from I2P
and forwards them to a given local port
:param sam_host:
:param sam_port:
:param target_port: Where to forward the I2P traffic to
:param priv_key: Private key of a destination as printed in the logs
"""
loop = asyncio.get_event_loop()
destination = None
if priv_key:
destination = Destination(priv_key, has_private_key=True)
logger = logging.getLogger("servers.server_tcp_tunnel")
logger.info("Starting a server tunnel for %s", target_port)
tunnel = i2plib.ServerTunnel(
("127.0.0.1", target_port),
destination=destination,
session_name=SESSION_NAME,
sam_address=(sam_host, sam_port),
loop=loop
)
await tunnel.run()
log_destination = destination
if not log_destination:
log_destination = tunnel.destination
logger.info("Started server with destination: %s", log_destination.base32)
# Log private key for later reuse
# TODO: Probably this isn't safe and we would provide another option
if not destination:
logger.info("Your private key is %s", log_destination.private_key.base64)
try:
await tunnel.server_loop
except KeyboardInterrupt:
pass
finally:
tunnel.stop()
logger.info("Server tunnel closed")

View File

@ -0,0 +1,18 @@
# i2p-docker-proxy
# Copyright (C) 2019 LoveIsGrief
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import typing
Base64 = typing.NewType('Base64', str)

View File

@ -27,7 +27,9 @@ services:
depends_on:
- i2pd
environment:
PROXY_SAM_HOST: 172.16.200.3 # First floodfill
PROXY_SAM_HOST: 172.16.200.4 # First non-floodfill
PROXY_SERVER_ACTIVE: 1
PROXY_SERVER_PORT: 8080
volumes:
- /tmp/contained:/mount
- ./contained/bin:/opt/bin