diff --git a/app/bootstrap.py b/app/bootstrap.py new file mode 100644 index 0000000..745b287 --- /dev/null +++ b/app/bootstrap.py @@ -0,0 +1,163 @@ +import os +import json +import uuid +import subprocess + + +def add_runner(runner_pool, content): + runner_id = str(uuid.uuid4()) + print('Adding runner {}...'.format(runner_id)) + + with open("/root/runner/{}.sh".format(runner_id), "w") as f: + f.write(content) + + subprocess.check_call(["chmod", "+x", "/root/runner/{}.sh".format(runner_id)]) + runner_pool.append(runner_id) + + +def run_cmd(args): + print("[Run] {}".format(' '.join(args))) + subprocess.check_call(args) + + +if __name__ == "__main__": + gateway_ip = os.getenv('GATEWAY_IP') + wg_port = os.getenv('WG_PORT') + + print('gateway ip is {}'.format(gateway_ip)) + + print('Adding hostname...') + with open('/etc/hosts', 'a') as f: + f.write('\n{} wgop.gateway\n'.format(gateway_ip)) + + runners = [] + + print('Reading bootstrap.json...') + with open('/root/conf/bootstrap.json') as f: + config = f.read() + config = json.loads(config) + + for idx, info in enumerate(config): + print('Loading {} of {} parts with type {}...'.format(idx + 1, len(config), info['type'])) + + if info['type'] == 'mux': + add_runner(runners, '''#!/bin/bash +exec /root/bin/mux -l {} -t {} -s {} +'''.format(info['listen'], info['forward'], info['size'])) + + elif info['type'] == 'udp2raw-client': + with open('/root/conf/{}.conf'.format(info['id']), 'w') as f: + f.write('-c\n-l 0.0.0.0:{}\n-r {}\n-k {}\n--raw-mode faketcp'.format(info['listen'], info['remote'], info['password'])) + + with open('/root/conf/{}-ipt.conf'.format(info['id']), 'w') as f: + f.write('-c\n-l 0.0.0.0:{}\n-r {}\n-k {}\n--raw-mode faketcp\n-g'.format(info['listen'], info['remote'], info['password'])) + + add_runner(runners, '''#!/bin/bash +exec /root/bin/udp2raw_amd64 --conf-file /root/conf/{}.conf +'''.format(info['id'])) + + elif info['type'] == 'udp2raw-server': + with open('/root/conf/{}.conf'.format(info['id']), 'w') as f: + f.write('-s\n-l 0.0.0.0:{}\n-r {}:{}\n-k {}\n--raw-mode faketcp'.format(info['listen'], gateway_ip, wg_port, info['password'])) + + with open('/root/conf/{}-ipt.conf'.format(info['id']), 'w') as f: + f.write('-s\n-l 0.0.0.0:{}\n-r {}:{}\n-k {}\n--raw-mode faketcp\n-g'.format(info['listen'], gateway_ip, wg_port, info['password'])) + + add_runner(runners, '''#!/bin/bash +exec /root/bin/udp2raw_amd64 --conf-file /root/conf/{}.conf +'''.format(info['id'])) + + elif info['type'] == 'gost-client': + add_runner(runners, '''#!/bin/bash +exec /root/bin/gost -L udp://:{} -F relay+tls://{} +'''.format(info['listen'], info['remote'])) + + elif info['type'] == 'gost-server': + add_runner(runners, '''#!/bin/bash +exec /root/bin/gost -L=relay+tls://:{}/{}:{} +'''.format(info['listen'], gateway_ip, wg_port)) + + elif info['type'] == 'trojan-client': + if ':' in info['remote']: + remote_parts = info['remote'].split(':') + remote_host = remote_parts[0] + remote_port = int(remote_parts[1]) + else: + remote_host = info['remote'] + remote_port = 443 + + jconfig = { + "run_type": "forward", + "local_addr": "0.0.0.0", + "local_port": info['listen'], + "remote_addr": remote_host, + "remote_port": remote_port, + "target_addr": "wgop.gateway", + "target_port": info['target'], + "log_level": 0, + "password": [info['password']], + "ssl": {} + } + + if info['sni']: + jconfig["ssl"]["sni"] = info['sni'] + else: + jconfig["ssl"]["sni"] = remote_host + + config_id = str(uuid.uuid4()) + with open("/root/conf/{}.json".format(config_id), "w") as f: + f.write(json.dumps(jconfig)) + + add_runner(runners, '''#!/bin/bash +exec /root/bin/trojan-go -config /root/conf/{}.json +'''.format(config_id)) + + elif info['type'] == 'trojan-server': + jconfig = { + "run_type": "server", + "local_addr": "0.0.0.0", + "local_port": info['listen'], + "remote_addr": "127.0.0.1", + "remote_port": 80, + "password": [info['password']], + "log_level": 0, + "ssl": { + "cert": "/root/ssl/{}.cert".format(info['cert']), + "key": "/root/ssl/{}.key".format(info['cert']), + "fallback_port": 80 + } + } + + config_id = str(uuid.uuid4()) + with open("/root/conf/{}.json".format(config_id), "w") as f: + f.write(json.dumps(jconfig)) + + add_runner(runners, '''#!/bin/bash +systemctl start nginx +exec /root/bin/trojan-go -config /root/conf/{}.json +'''.format(config_id)) + else: + print('Unknown type: {}'.format(info['type'])) + + print('Adding service template...') + with open("/lib/systemd/system/wg-ops-runner@.service", "w") as f: + f.write('''[Unit] +Description=WireGuard Ops Serivce Runner for %I + +[Service] +Type=simple +ExecStart=/bin/bash /root/runner/%i.sh +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=multi-user.target +''') + + run_cmd(["systemctl", "daemon-reload"]) + + for idx, runner_id in enumerate(runners): + print("Starting runner {} of {}...".format(idx + 1, len(runners))) + run_cmd(["systemctl", "start", "wg-ops-runner@{}".format(runner_id)]) + + print('Bootstrap finished.')