-
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.
- Loading branch information
Showing
21 changed files
with
736 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*__pycache__ | ||
*pyc | ||
*pyo | ||
*so |
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,2 @@ | ||
ReverseProxy/tlsheader.so: tlsheader.c | ||
gcc tlsheader.c -o ReverseProxy/tlsheader.so -fPIC -shared |
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,2 @@ | ||
from .reactor import reactor | ||
from . import _click |
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,23 @@ | ||
import click | ||
import functools | ||
click.core._verify_python3_env = lambda *x: None | ||
|
||
_main = click.core.BaseCommand.main | ||
|
||
|
||
@functools.partial(setattr, click.core.BaseCommand, 'main') | ||
def main(self, args: []=None, prog_name: str=None, complete_var: str=None, standalone_mode: bool=True, **extra): | ||
if args and prog_name is None: | ||
prog_name = args[0] | ||
args = args[1:] | ||
else: | ||
args = None | ||
|
||
if not standalone_mode: | ||
ctx = self.make_context(prog_name, args) | ||
with ctx: | ||
self.invoke(ctx) | ||
return ctx | ||
|
||
return _main(self, args, prog_name, complete_var, standalone_mode, **extra) | ||
|
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,25 @@ | ||
import socket | ||
import array | ||
|
||
|
||
def send_fd(sock, fd, msg=b"0"): | ||
return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", [fd]))]) | ||
|
||
|
||
def recv_fd(sock, msglen=1): | ||
fds = array.array("i") | ||
msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(fds.itemsize)) | ||
for cmsg_level, cmsg_type, cmsg_data in ancdata: | ||
if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS): | ||
# Append data, ignoring any truncated integers at the end. | ||
fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) | ||
return list(fds)[0] | ||
|
||
|
||
def send_fd_to(path, sock): | ||
if not isinstance(sock, int): | ||
sock = sock.fileno() | ||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
s.connect(path) | ||
send_fd(s, sock) | ||
|
Empty file.
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,23 @@ | ||
import sys | ||
|
||
from twisted.internet.protocol import ServerFactory | ||
|
||
from .configuration import Configuration | ||
from .click import cli | ||
from ..reactor import reactor | ||
from .receiver import FDReceiverProtocol | ||
import click.core | ||
click.core.Exit = SystemExit | ||
|
||
def __main__(argv=sys.argv): | ||
from twisted.python.log import startLogging | ||
startLogging(sys.stderr) | ||
configuration: Configuration = cli.main(argv, standalone_mode=False).obj | ||
reactor.listenUNIX(configuration.listenPort, ServerFactory.forProtocol(lambda: FDReceiverProtocol(configuration))) | ||
return reactor.run() | ||
|
||
if __name__=='__main__': | ||
argv = sys.argv | ||
argv[0] = __package__ | ||
raise SystemExit(__main__(argv)) | ||
|
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,41 @@ | ||
from click import group, option, pass_context, pass_obj | ||
from twisted.protocols import tls | ||
|
||
from twisted.python.filepath import FilePath | ||
import importlib.util | ||
|
||
|
||
from .configuration import Configuration | ||
from .ssl import makeContextFactory | ||
|
||
|
||
@group(invoke_without_command=True, chain=True) | ||
@option("--listenPort", type=str, required=True) | ||
@pass_context | ||
def cli(context, listenport): | ||
context.obj = Configuration(listenport) | ||
|
||
|
||
@cli.command() | ||
@pass_obj | ||
@option("--privkey", type=str, required=True) | ||
@option("--cert", type=str, required=True) | ||
@option("--chain", type=str, required=True) | ||
def ssl(conf: Configuration, privkey, cert, chain): | ||
conf.certificate = FilePath(cert) | ||
conf.chain = FilePath(chain) | ||
conf.privateKey = FilePath(privkey) | ||
conf.sslFactory = makeContextFactory(conf) | ||
if conf.factory: | ||
conf.tlsFactory = tls.TLSMemoryBIOFactory(conf.sslFactory, False, conf.factory) | ||
|
||
|
||
@cli.command() | ||
@pass_obj | ||
@option("--application", type=str, required=True) | ||
def launch(conf: Configuration, application: str): | ||
module, attribute = application.rsplit('.', 1) | ||
mod = importlib.import_module(module) | ||
conf.factory = getattr(mod, attribute) | ||
if conf.sslFactory: | ||
conf.tlsFactory = tls.TLSMemoryBIOFactory(conf.sslFactory, False, conf.factory) |
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,12 @@ | ||
import attr | ||
|
||
|
||
@attr.s() | ||
class Configuration(object): | ||
listenPort: str = attr.ib() | ||
sslFactory = attr.ib(None) | ||
privateKey = attr.ib(None) | ||
certificate = attr.ib(None) | ||
chain = attr.ib(None) | ||
factory = attr.ib(None) | ||
tlsFactory = attr.ib(None) |
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,32 @@ | ||
from twisted.internet.interfaces import IFileDescriptorReceiver | ||
from twisted.internet.protocol import Protocol | ||
from zope.interface import implementer | ||
|
||
import socket | ||
|
||
from .. import reactor | ||
from ..parsers import is_ssl | ||
|
||
|
||
@implementer(IFileDescriptorReceiver) | ||
class FDReceiverProtocol(Protocol): | ||
descriptor = None | ||
|
||
def __init__(self, conf): | ||
self.conf = conf | ||
|
||
def fileDescriptorReceived(self, descriptor): | ||
# Record the descriptor sent to us | ||
self.descriptor = descriptor | ||
sock = socket.fromfd(descriptor, socket.AF_INET, socket.SOCK_STREAM) | ||
try: | ||
peek = sock.recv(1024, socket.MSG_PEEK) | ||
finally: | ||
sock.close() | ||
|
||
if is_ssl(peek) and self.conf.tlsFactory: | ||
reactor.adoptStreamConnection(descriptor, socket.AF_INET, self.conf.tlsFactory) | ||
|
||
else: | ||
reactor.adoptStreamConnection(descriptor, socket.AF_INET, self.conf.factory) | ||
|
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,30 @@ | ||
from twisted.internet import ssl | ||
|
||
|
||
# noinspection PyMissingConstructor | ||
class OpenSSLContextFactory(ssl.DefaultOpenSSLContextFactory): | ||
def __init__(self, privateKeyFileName, certificateFileName, chainFileName): | ||
self.sslmethod = ssl.SSL.SSLv23_METHOD | ||
self.privateKeyFileName = privateKeyFileName | ||
self.certificateFileName = certificateFileName | ||
self.chainFileName = chainFileName | ||
self.cacheContext() | ||
|
||
def cacheContext(self): | ||
if self._context is None: | ||
ctx = ssl.SSL.Context(self.sslmethod) | ||
# Disallow SSLv2! It's insecure! SSLv3 has been around since | ||
# 1996. It's time to move on. | ||
ctx.set_options(ssl.SSL.OP_NO_SSLv2) | ||
ctx.set_options(ssl.SSL.OP_NO_SSLv3) | ||
ctx.set_options(ssl.SSL.OP_NO_TLSv1) | ||
ctx.set_options(ssl.SSL.OP_NO_TLSv1_1) | ||
ctx.use_certificate_chain_file(self.chainFileName) | ||
ctx.use_certificate_file(self.certificateFileName) | ||
ctx.use_privatekey_file(self.privateKeyFileName) | ||
|
||
self._context = ctx | ||
|
||
|
||
def makeContextFactory(conf): | ||
return OpenSSLContextFactory(conf.privateKey.path, conf.certificate.path, conf.chain.path) |
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,51 @@ | ||
from twisted.python.filepath import FilePath | ||
import ctypes | ||
tlsheader = ctypes.cdll.LoadLibrary(FilePath(__file__).sibling('tlsheader.so').path) | ||
tlsheader.parseHeader.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p] | ||
|
||
|
||
def parse_tls(data): | ||
out = ctypes.create_string_buffer(255) | ||
datalen = len(data) | ||
success = tlsheader.parseHeader(data, datalen, out) | ||
return success, out.value | ||
|
||
|
||
def parse_http(data): | ||
data = data.replace(b'\r\n', b'\n').split(b'\n\n')[0] | ||
|
||
if b'Host' not in data: | ||
return None | ||
|
||
host = data.split(b'Host:', 1)[1].split(b'\n')[0].strip().split(b':')[0] | ||
return host | ||
|
||
|
||
def parse_host(data): | ||
if data[:3].isalpha(): | ||
try: | ||
host = parse_http(data) | ||
if host: | ||
return host | ||
success, host = parse_tls(data) | ||
if success > -1: | ||
return host | ||
except: | ||
return None | ||
else: | ||
success, host = parse_tls(data) | ||
if success > -1: | ||
return host | ||
if success == -2: | ||
return None | ||
|
||
return parse_http(data) | ||
|
||
|
||
def is_ssl(data): | ||
success, host = parse_tls(data) | ||
if success > -1 or success == -2: | ||
return True | ||
|
||
|
||
__all__ = ['parse_host', 'is_ssl'] |
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,6 @@ | ||
from twisted.internet.epollreactor import EPollReactor | ||
from twisted.internet.main import installReactor | ||
reactor: EPollReactor = EPollReactor() | ||
|
||
installReactor(reactor) | ||
|
Empty file.
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,22 @@ | ||
import sys | ||
|
||
from .click import cli | ||
from .proxy import run | ||
import click.core | ||
click.core.Exit = SystemExit | ||
|
||
|
||
def __main__(argv=sys.argv): | ||
from twisted.python.log import startLogging | ||
startLogging(sys.stderr) | ||
configuration = cli.main(argv, standalone_mode=False).obj | ||
return run(configuration) | ||
|
||
|
||
if __name__=='__main__': | ||
argv = sys.argv | ||
argv[0] = __package__ | ||
|
||
raise SystemExit(__main__(argv)) | ||
|
||
|
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,18 @@ | ||
from click import group, option, pass_context, pass_obj | ||
from .configuration import Configuration | ||
|
||
|
||
@group(chain=True) | ||
@option("--listenPort", default=443, type=int) | ||
@option("--listenInterface", default="", type=str) | ||
@pass_context | ||
def cli(context, listenport, listeninterface): | ||
context.obj = Configuration(listenport, listeninterface) | ||
|
||
|
||
@cli.command() | ||
@pass_obj | ||
@option("--hostname", type=str, required=True) | ||
@option("--socket", type=str, required=True) | ||
def vhost(conf: Configuration, socket: str, hostname: str): | ||
conf.addVHost(hostname, socket) |
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,19 @@ | ||
import attr | ||
import re | ||
|
||
|
||
@attr.s() | ||
class VHost(object): | ||
socket: str = attr.ib() | ||
hostname = attr.ib(converter=lambda x: re.compile(bytes(x, 'charmap'))) | ||
|
||
|
||
@attr.s() | ||
class Configuration(object): | ||
listenPort: int = attr.ib() | ||
listenInterface: str = attr.ib() | ||
|
||
vhosts: list = attr.ib(default=attr.Factory(list)) | ||
|
||
def addVHost(self, hostname, socket): | ||
self.vhosts.append(VHost(socket, hostname)) |
Oops, something went wrong.