From 8d1f2ceadac382c6ea42ee3e29633cf99de1a58d Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 8 Jul 2019 18:27:11 +0200 Subject: generate eip-service.json --- .gitignore | 1 + Makefile | 5 ++ config/.demo.yaml.swp | Bin 0 -> 12288 bytes config/demo.yaml | 33 +++++++++++++ main.go | 3 ++ scripts/gen-shapeshifter-state.py | 62 +++++++++++++++++++++++++ scripts/simplevpn.py | 79 ++++++++++++++++++++++++++++++++ scripts/templates/.eip-service.json.swp | Bin 0 -> 12288 bytes scripts/templates/eip-service.json | 32 +++++++++++++ 9 files changed, 215 insertions(+) create mode 100644 config/.demo.yaml.swp create mode 100644 config/demo.yaml create mode 100755 scripts/gen-shapeshifter-state.py create mode 100755 scripts/simplevpn.py create mode 100644 scripts/templates/.eip-service.json.swp create mode 100644 scripts/templates/eip-service.json diff --git a/.gitignore b/.gitignore index 59c1baa..8b0235d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ vpnweb +deploy/* diff --git a/Makefile b/Makefile index b8fe777..023972c 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,11 @@ demo: clean: rm -f public/1/* rm public/ca.crt +gen-shapeshifter: + scripts/gen-shapeshifter-state.py deploy/shapeshifter-state +gen-provider: + mkdir -p deploy/public/3 + python3 scripts/simplevpn.py config/demo.yaml scripts/templates/eip-service.json --obfs4_state deploy/shapeshifter-state > deploy/public/3/eip-service.json populate: cp test/1/* public/1/ cp test/files/ca.crt public/ diff --git a/config/.demo.yaml.swp b/config/.demo.yaml.swp new file mode 100644 index 0000000..b673bd7 Binary files /dev/null and b/config/.demo.yaml.swp differ diff --git a/config/demo.yaml b/config/demo.yaml new file mode 100644 index 0000000..5743304 --- /dev/null +++ b/config/demo.yaml @@ -0,0 +1,33 @@ +openvpn: + + - auth: SHA1 + - cipher: AES-256-CBC + - keepalive: "10 30" + - tls-cipher: DHE-RSA-AES128-SHA + - tun-ipv6: true + - dev: tun + - sndbuf: 0 + - rcvbuf: 0 + - nobind: true + - persist-key: true + - key-direction: 1 + - verb: 3 + +locations: + + - Amsterdam: + - name: Amsterdam + - country_code: NL + - hemisphere: N + - timezone: -1 + + +gateways: + + - pt.demo.bitmask.net: + - host: pt.demo.bitmask.net + - ip_address: 37.218.247.60 + - location: Amsterdam + - transports: + - [ "openvpn", "tcp", "443"] + - [ "obfs4", "tcp", "23042"] diff --git a/main.go b/main.go index d88c20c..a6da11c 100644 --- a/main.go +++ b/main.go @@ -66,9 +66,12 @@ func main() { // add routes here http.HandleFunc("/1/cert", ch.certResponder) + http.HandleFunc("/3/cert", ch.certResponder) httpFileHandler("/1/ca.crt", "./public/ca.crt") httpFileHandler("/1/configs.json", "./public/1/configs.json") httpFileHandler("/1/service.json", "./public/1/service.json") + httpFileHandler("/3/service.json", "./public/3/service.json") + httpFileHandler("/3/service.json", "./public/3/eip-service.json") pstr := ":" + strconv.Itoa(*port) diff --git a/scripts/gen-shapeshifter-state.py b/scripts/gen-shapeshifter-state.py new file mode 100755 index 0000000..e7b1ff2 --- /dev/null +++ b/scripts/gen-shapeshifter-state.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +""" +Generates the Curve25519 keypair that is needed by the shapeshifter-dispatcher +server. + +Depends on python3-axolotl-curve25519 package. +""" + +import base64 +import json +import os + +import pysodium +import binascii + +BRIDGE_PREAMBLE = "Bridge obfs4 : cert=" +BRIDGE_END = " iat-mode=0" + + +def generate(statedir): + try: + os.makedirs(statedir) + except Exception: + pass + print("[+] Generating shapeshifter parameters...") + + public, private = pysodium.crypto_box_keypair() + + priv_hex = binascii.b2a_hex(private) + pub_hex = binascii.b2a_hex(public) + node_id = os.urandom(20) + node_id_hex = binascii.b2a_hex(node_id) + drbg_seed = os.urandom(24) + + def tostr(b): + return b.decode('utf-8') + + with open(statedir + '/obfs4_state.json', 'w') as state: + state.write(json.dumps({ + 'node-id': tostr(node_id_hex), + 'private-key': tostr(priv_hex), + 'public-key': tostr(pub_hex), + 'drbg-seed': tostr(binascii.b2a_hex(drbg_seed)), + 'iat-mode': 0})) + + cert = base64.b64encode(node_id + pub_hex) + print("CERT:", cert) + + with open(statedir + '/obfs4_cert.txt', 'w') as certf: + certf.write(tostr(cert).rstrip('=')) + + with open(statedir + '/obfs4_bridgeline.txt', 'w') as bridgef: + bridgef.write(BRIDGE_PREAMBLE + tostr(cert) + BRIDGE_END) + print("[+] done") + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("statedir") + args = parser.parse_args() + generate(args.statedir) diff --git a/scripts/simplevpn.py b/scripts/simplevpn.py new file mode 100755 index 0000000..7906e7c --- /dev/null +++ b/scripts/simplevpn.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +import argparse +import os + +import yaml + +from jinja2 import Template + + +class EIPConfig: + def __init__(self): + self.openvpn = dict() + self.locations = dict() + self.gateways = dict() + self.obfs4_cert = "" + + +def parseConfig(provider_config): + with open(provider_config) as conf: + config = yaml.load(conf.read()) + eip = EIPConfig() + eip.openvpn.update(yamlListToDict(config['openvpn'])) + + for loc in config['locations']: + eip.locations.update(yamlIdListToDict(loc)) + for gw in config['gateways']: + eip.gateways.update(yamlIdListToDict(gw)) + return eip + + +def yamlListToDict(values): + vals = {} + for d in values: + for k, v in d.items(): + vals[k] = v + return vals + + +def yamlIdListToDict(data): + _d = {} + for identifier, values in data.items(): + _d[identifier] = yamlListToDict(values) + return _d + + +def patchObfs4Cert(config, cert): + for gw in config.gateways: + for options in config.gateways[gw]['transports']: + opts = {} + transport, _, _ = options + if transport == "obfs4": + opts['cert'] = cert + opts['iat-mode'] = 0 + options.append(opts) + return config + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("provider_config") + parser.add_argument("eip_template") + parser.add_argument("--obfs4_state") + args = parser.parse_args() + + config = parseConfig(os.path.abspath(args.provider_config)) + + if args.obfs4_state: + obfs4_cert = open( + args.obfs4_state + '/obfs4_cert.txt').read().rstrip() + else: + obfs4_cert = None + patchObfs4Cert(config, obfs4_cert) + + t = Template(open(args.eip_template).read()) + + print(t.render( + locations=config.locations, + gateways=config.gateways, + openvpn=config.openvpn)) diff --git a/scripts/templates/.eip-service.json.swp b/scripts/templates/.eip-service.json.swp new file mode 100644 index 0000000..284242a Binary files /dev/null and b/scripts/templates/.eip-service.json.swp differ diff --git a/scripts/templates/eip-service.json b/scripts/templates/eip-service.json new file mode 100644 index 0000000..8d1b0a1 --- /dev/null +++ b/scripts/templates/eip-service.json @@ -0,0 +1,32 @@ +{ + "serial": 3, + "version": 3, + "locations": { {% for loc in locations %} + "{{loc}}": { + "name": "{{ locations[loc]["name"] }}", + "country_code": "{{ locations[loc]["country_code"] }}", + "hemisphere": "{{ locations[loc]["hemisphere"] }}", + "timezone": {{ locations[loc]["timezone"] }}, + },{% endfor %} + }, + "gateways": { {% for gw in gateways %} + "{{gw}}": { + "host": "{{ gateways[gw]["host"] }}", + "ip_address": "{{ gateways[gw]["ip_address"] }}", + "location": "{{ gateways[gw]["location"] }}", + "capabilities": { + "adblock": false, + "filter_dns": false, + "limited": false, + "transport": [ {% for tr, proto, port, options in gateways[gw]["transports"] %} + {"type": "{{ tr }}", + "protocols": ["{{ proto }}"], + "ports": [{{ port }}],{% if options %} + "options": {{ options | tojson }},{% endif %} + },{% endfor %} + ], + }, + },{% endfor %} + }, + "openvpn_configuration": {{ openvpn|tojson(indent=8) }} +} -- cgit v1.2.3