Per-Arne Andersen
4 years ago
committed by
GitHub
2 changed files with 200 additions and 10 deletions
@ -0,0 +1,173 @@ |
|||
import os |
|||
from threading import Thread |
|||
|
|||
from script.obfuscate import BaseObfuscation, NotInstalledError |
|||
import re |
|||
import pathlib |
|||
import shutil |
|||
|
|||
current_dir = pathlib.Path(__file__).parent.absolute() |
|||
shapeshifter_path = current_dir.joinpath("binary/shapeshifter-dispatcher") |
|||
shapeshifter_binary = shapeshifter_path.joinpath("shapeshifter-dispatcher") |
|||
|
|||
|
|||
class GoNotFound(Exception): |
|||
pass |
|||
|
|||
|
|||
class GoVersionIncompatible(Exception): |
|||
pass |
|||
|
|||
|
|||
class GitNotInstalled(Exception): |
|||
pass |
|||
|
|||
|
|||
class ShapeShifterBase(BaseObfuscation): |
|||
MODES_SUPPORTED = ["server", "client"] |
|||
ALGORITHMS_SUPPORTED = ["obfs4"] |
|||
|
|||
def __init__(self, mode, algorithm, wireguard_port=None, listen_port=None, client_replicant_port=None, client_options=None): |
|||
super().__init__( |
|||
binary_path=shapeshifter_binary, |
|||
algorithm=algorithm |
|||
) |
|||
|
|||
assert mode in ShapeShifterBase.MODES_SUPPORTED, "%s is not a supported mode. Supported: %s" % ( |
|||
mode, ShapeShifterBase.MODES_SUPPORTED |
|||
) |
|||
|
|||
self._wireguard_port = wireguard_port |
|||
self._listen_port = listen_port |
|||
self._client_replicant_port = client_replicant_port |
|||
self._mode = mode |
|||
self._client_options = client_options |
|||
|
|||
self._go_version_min = (1, 14, 0) |
|||
|
|||
self.ensure_installed() |
|||
|
|||
def _verify_go_installed(self): |
|||
output, code = self.execute("version", override_command="go") |
|||
|
|||
try: |
|||
match = re.findall("go([0-9]+.[0-9]+.[0-9]+)", output) |
|||
match = match[0] |
|||
except IndexError: |
|||
raise GoNotFound("Go was not found on the system.") |
|||
|
|||
major, minor, patch = match.split(".") |
|||
|
|||
if int(major) < self._go_version_min[0] or int(minor) < self._go_version_min[1] or \ |
|||
int(patch) < self._go_version_min[2]: |
|||
raise GoVersionIncompatible("Go version is incompatible. %s < %s" % (self._go_version_min, match)) |
|||
|
|||
def _verify_git_installed(self): |
|||
output, code = self.execute("version", override_command="git") |
|||
if code == 0: |
|||
return |
|||
|
|||
raise GitNotInstalled("Git does not seem to be installed. Code: %s, Output: %s" % (code, output)) |
|||
|
|||
def _verify_shapeshifter_installed(self): |
|||
output, code = self.execute("version", override_command=shapeshifter_binary) |
|||
print(output, code) |
|||
|
|||
def _install_shapeshifter(self): |
|||
|
|||
if shapeshifter_path.is_dir(): |
|||
shutil.rmtree(shapeshifter_path) |
|||
|
|||
output, code = self.execute( |
|||
"clone", |
|||
"https://github.com/OperatorFoundation/shapeshifter-dispatcher.git", |
|||
shapeshifter_path, |
|||
override_command="git") |
|||
|
|||
assert code == 0, "Git exited with error. %s" % (output,) |
|||
|
|||
current_working_dir = os.getcwd() |
|||
os.chdir(shapeshifter_path) |
|||
|
|||
output, code = self.execute("build", override_command="go") |
|||
os.chdir(current_working_dir) |
|||
|
|||
assert code == 0, "Building shapeshifter failed with output: %s" % (output,) |
|||
|
|||
def ensure_installed(self): |
|||
try: |
|||
super().ensure_installed() |
|||
except NotInstalledError: |
|||
|
|||
self._verify_go_installed() |
|||
self._verify_git_installed() |
|||
|
|||
try: |
|||
self._verify_shapeshifter_installed() |
|||
except FileNotFoundError: |
|||
self._install_shapeshifter() |
|||
|
|||
def start(self): |
|||
|
|||
bind_command = "bindaddr" if self._mode == "server" else "proxylistenaddr" |
|||
bind_port = self._listen_port if self._mode == "server" else self._client_replicant_port |
|||
bind_value = f"127.0.0.1:{bind_port}" # TODO |
|||
if self._mode == "server": |
|||
bind_value = self.algorithm + "-" + bind_value |
|||
connect_command = "orport" if self._mode == "server" else "target" |
|||
connect_port = self._wireguard_port if self._mode == "server" else self._listen_port |
|||
|
|||
cmd = [ |
|||
"-transparent", |
|||
"-udp", |
|||
f"-{self._mode}", |
|||
"-state", f"state", |
|||
f"-{connect_command}", f"127.0.0.1:{connect_port}", |
|||
"-transports", self.algorithm, |
|||
f"-{bind_command}", bind_value |
|||
] |
|||
|
|||
if self._mode == "client": |
|||
cmd.extend([ |
|||
"-options", f"{self._client_options}" |
|||
]) |
|||
|
|||
cmd.extend([ |
|||
"-logLevel", "DEBUG", |
|||
"-enableLogging", |
|||
]) |
|||
print(*cmd) |
|||
output, code = self.execute(*cmd, stream=True, prefix=self._mode) |
|||
print(output, code) |
|||
|
|||
def start_threaded(self): |
|||
t = Thread(target=self.start, args=()) |
|||
t.start() |
|||
return t |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
import time |
|||
x = ShapeShifterBase( |
|||
mode="server", |
|||
algorithm="obfs2", |
|||
wireguard_port=3333, |
|||
listen_port=2222, |
|||
) |
|||
x.start_threaded() |
|||
|
|||
time.sleep(1) |
|||
|
|||
x = ShapeShifterBase( |
|||
mode="client", |
|||
algorithm="obfs2", |
|||
listen_port=2222, |
|||
client_replicant_port=1443, |
|||
client_options='{"cert": "BWvGMVn3C8daXai2Xo+If23XS94eztZE9Kbtykvy9x5ADWc6YCHdGlWQfDh1fzu7AhuTIA", "iat-mode": "0"}' |
|||
) |
|||
x.start_threaded() |
|||
|
|||
|
|||
|
|||
while True: |
|||
time.sleep(1) |
Loading…
Reference in new issue