Back to basics: wg-quick extend comment

This commit is contained in:
Kirigaya Kazuto 2022-01-24 11:11:47 +00:00
parent 4174606921
commit ea89859850
8 changed files with 184 additions and 743 deletions

184
generate.py Normal file
View File

@ -0,0 +1,184 @@
import os
import sys
import time
filepath = sys.argv[1]
path_udp2raw = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 'bin/udp2raw_amd64')
path_w2u = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 'bin/w2u')
path_gost = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 'bin/gost')
filename = os.path.basename(filepath)
wg_name = filename.split('.')[0]
with open(filename, 'r') as f:
content = f.read().split('\n')
gen_ctx = {
'tunnels': {},
'post_down': [],
}
results = []
def add_tmux_session_once():
if 'has_setup_tmux' not in gen_ctx:
gen_ctx['has_setup_tmux'] = True
results.append('''PostUp=/usr/bin/tmux new-session -s tunnel-{} -d 'watch -n 1 --color WG_COLOR_MODE=always wg show {}' '''.format(wg_name, wg_name))
for line in content:
if line.startswith('ListenPort'):
gen_ctx['wg_port'] = int(line.split('=')[1])
if line.startswith('[Peer]'):
if 'peer_started' not in gen_ctx:
gen_ctx['peer_started'] = True
if gen_ctx['post_down']:
results.extend(gen_ctx['post_down'])
if 'has_setup_tmux' in gen_ctx:
results.append('PostDown=sleep 1; /usr/bin/tmux kill-session -t tunnel-{}'.format(wg_name))
if not line.startswith('#'):
results.append(line)
continue
if line.startswith('#enable-bbr'):
results.append('PostUp=sysctl net.core.default_qdisc=fq\nPostUp=sysctl net.ipv4.tcp_congestion_control=bbr')
elif line.startswith('#enable-forward'):
results.append('PostUp=sysctl net.ipv4.ip_forward=1')
elif line.startswith('#iptables-forward'):
results.append('PostUp=iptables -A FORWARD -i {} -j ACCEPT')
elif line.startswith('#udp2raw-server'):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_port = parts[1]
tunnel_passwd = parts[2]
add_tmux_session_once()
results.append('''PostUp=/usr/bin/echo -e '-s\\n-l 0.0.0.0:{}\\n-r 127.0.0.1:{}\\n-k {}\\n--raw-mode faketcp\\n--fix-gro\\n-a' > /tmp/temp-udp2raw-{}.conf'''.format(
tunnel_port, gen_ctx['wg_port'], tunnel_passwd, tunnel_name
))
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} --conf-file /tmp/temp-udp2raw-{}.conf'; sleep 2'''.format(
wg_name, path_udp2raw, tunnel_name
))
results.append('''PostUp=/usr/bin/rm /tmp/temp-udp2raw-{}.conf'''.format(tunnel_name))
elif line.startswith('#udp2raw-client '):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_port = parts[1]
tunnel_remote = parts[2]
tunnel_passwd = parts[3]
gen_ctx['tunnels'][tunnel_name] = tunnel_port
add_tmux_session_once()
results.append('''PostUp=/usr/bin/echo -e '-c\\n-l 127.0.0.1:{}\\n-r {}\\n-k {}\\n--raw-mode faketcp\\n--fix-gro\\n-a' > /tmp/temp-udp2raw-{}.conf'''.format(
tunnel_port, tunnel_remote, tunnel_passwd, tunnel_name
))
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -n {}-win -d '{} --conf-file /tmp/temp-udp2raw-{}.conf'; sleep 2'''.format(
wg_name, tunnel_name, path_udp2raw, tunnel_name
))
results.append('''PostUp=/usr/bin/rm /tmp/temp-udp2raw-{}.conf'''.format(tunnel_name))
gen_ctx['post_down'].append('''PostDown=/usr/bin/tmux send-keys -t {}-win C-c '''.format(tunnel_name))
elif line.startswith('#udp2raw-client-mux '):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_mux = int(parts[1])
tunnel_port = int(parts[2])
tunnel_remote = parts[3]
tunnel_passwd = parts[4]
gen_ctx['tunnels'][tunnel_name] = tunnel_port
add_tmux_session_once()
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} -f {} -l {} -t {} -s {}' '''.format(
wg_name, path_w2u, gen_ctx['wg_port'], tunnel_port, tunnel_port + 1, tunnel_mux
))
for mux_idx in range(tunnel_mux):
results.append('''PostUp=/usr/bin/echo -e '-c\\n-l 127.0.0.1:{}\\n-r {}\\n-k {}\\n--raw-mode faketcp\\n--fix-gro\\n-a' > /tmp/temp-udp2raw-{}-{}.conf'''.format(
tunnel_port + 1 + mux_idx, tunnel_remote, tunnel_passwd, tunnel_name, mux_idx
))
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -n {}-win-{} -d '{} --conf-file /tmp/temp-udp2raw-{}-{}.conf'; sleep 2'''.format(
wg_name, tunnel_name, mux_idx, path_udp2raw, tunnel_name, mux_idx
))
results.append('''PostUp=/usr/bin/rm /tmp/temp-udp2raw-{}-{}.conf'''.format(tunnel_name, mux_idx))
gen_ctx['post_down'].append('''PostDown=/usr/bin/tmux send-keys -t {}-win-{} C-c '''.format(tunnel_name, mux_idx))
elif line.startswith('#gost-server '):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_port = parts[1]
add_tmux_session_once()
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} -L=relay+tls://:{}/127.0.0.1:{}' '''.format(
wg_name, path_gost, tunnel_port, gen_ctx['wg_port']
))
elif line.startswith('#gost-client '):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_port = parts[1]
tunnel_remote = parts[2]
gen_ctx['tunnels'][tunnel_name] = tunnel_port
add_tmux_session_once()
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} -L udp://:{} -F relay+tls://{}' '''.format(
wg_name, path_gost, tunnel_port, tunnel_remote
))
elif line.startswith('#gost-client-mux '):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_mux = int(parts[1])
tunnel_port = int(parts[2])
tunnel_remote = parts[3]
gen_ctx['tunnels'][tunnel_name] = tunnel_port
add_tmux_session_once()
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} -f {} -l {} -t {} -s {}' '''.format(
wg_name, path_w2u, gen_ctx['wg_port'], tunnel_port, tunnel_port + 1, tunnel_mux
))
for mux_idx in range(tunnel_mux):
results.append('''PostUp=/usr/bin/tmux new-window -t tunnel-{} -d '{} -L udp://:{} -F relay+tls://{}' '''.format(
wg_name, path_gost, tunnel_port + 1 + mux_idx, tunnel_remote
))
elif line.startswith('#use-tunnel'):
parts = line.split(' ')[1:]
tunnel_name = parts[0]
tunnel_port = gen_ctx['tunnels'][tunnel_name]
results.append('Endpoint=127.0.0.1:{}'.format(tunnel_port))
elif line.startswith('#route'):
parts = line.split(' ')[1:]
route_target = parts[0]
if 'disable_table' not in gen_ctx:
gen_ctx['disable_table'] = True
results.insert(1, 'Table=off')
# find last post-up
prev_postup = False
last_postup_idx = 0
for i in range(len(results)):
if results[i].startswith('PostUp='):
prev_postup = True
continue
if prev_postup:
last_postup_idx = i
break
if not last_postup_idx:
results.append('PostUp=ip -4 route add {} dev wg0'.format(route_target))
else:
results.insert(last_postup_idx, 'PostUp=ip -4 route add {} dev wg0'.format(route_target))
else:
print('[WARN] comment or unknown hint: {}'.format(line))
with open('{}.gen'.format(filename), 'w') as f:
f.write('# Generated by wg-ops at {}. DO NOT EDIT\n'.format(time.strftime("%Y-%m-%d %H:%M:%S")))
f.write('\n'.join(results))

View File

@ -1,14 +0,0 @@
#!/bin/bash
export WG_MYPRIK=$(wg genkey)
export WG_MYPUBK=$(echo $WG_MYPRIK | wg pubkey)
export TMUX_PATH=$(which tmux)
python3 wgop_quick_client.py
python3 wgop_generate.py
chmod +x start.sh
chmod +x stop.sh
chmod +x restart.sh
chmod +x reload.sh

View File

@ -1,6 +0,0 @@
#!/bin/bash
echo 'Detecting Public IP address...'
export WG_PUBLICIP=$(curl ident.me)
python3 wgop_display.py

View File

@ -1,175 +0,0 @@
# -*- coding: utf-8 -*-
import logging
import json
import traceback
import base64
import hashlib
import random
import string
# Constants
WGOP_USPEEDER_S_PBEGIN = 27100
WGOP_USPEEDER_C_PBEGIN = 28100
WGOP_LB_PBEGIN = 29000
WGOP_UC_PBEGIN = 29100
class SimpleLogger(object):
def __init__(self, name=None, filename=None, fileonly=False,
level=logging.INFO,
default_encoding='utf-8',
log_format="%(asctime)s @%(module)s [%(levelname)s] %(funcName)s: %(message)s"):
if name is None:
name = __name__
if not filename and fileonly:
raise Exception("FileOnly=True but no filename provided.")
self.logger = logging.getLogger(name)
if not getattr(self.logger, "_is_configured", None):
formatter = logging.Formatter(log_format)
if not fileonly:
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler)
if filename is not None:
file_handler = logging.FileHandler(filename, encoding=default_encoding)
file_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
self.logger.setLevel(level)
setattr(self.logger, "_is_configured", True)
# Just acts as a logger
def __getattr__(self, name):
return getattr(self.logger, name)
logger = SimpleLogger()
def load_config(filename=None):
config_filename = filename or "local/config.json"
try:
with open(config_filename) as f:
return json.loads(f.read())
except Exception:
logger.error("Unable to load config: {}".format(traceback.format_exc()))
return {}
def save_config(config, filename=None):
config_filename = filename or "local/config.json"
content = json.dumps(config, ensure_ascii=False, default=str, indent=2)
try:
with open(config_filename, "w", encoding='utf-8') as f:
f.write(content)
except Exception:
logger.error("Unable to save config: {}".format(traceback.format_exc()))
logger.info("Config:\n{}".format(content))
def json_to_base64(content):
return base64.b64encode(json.dumps(content, ensure_ascii=False).encode('utf-8')).decode('utf-8')
def base64_to_json(content):
return json.loads(base64.b64decode(content).decode('utf-8'))
def get_sha256(content):
return hashlib.sha256(content.encode('utf-8')).hexdigest()
def get_randpass(length):
return ''.join(random.choices(string.ascii_uppercase, k=2) + random.choices(string.ascii_lowercase + string.ascii_uppercase + string.digits, k=length - 2))
def get_quick_config(config, server_public_ip):
if config["ip"].endswith(".1"):
suggest_allowed = "{}.0/24".format('.'.join(config["ip"].split('.')[:-1]))
else:
suggest_allowed = config["ip"]
quicks = []
for server_info in config["udp2raw"]["server"]:
speeder_info = server_info["speeder"]
quick_config = {
"pubkey": config["pubkey"],
"allowed": suggest_allowed,
"remote": "{}:{}".format(server_public_ip, server_info["port"]),
"password": server_info["password"],
"ratio": speeder_info["ratio"] if speeder_info else None
}
quicks.append({
"port": server_info["port"],
"qcs": "#QCS#{}".format(json_to_base64(quick_config))
})
return quicks
class UConfigController:
next_port_speeder_server = WGOP_USPEEDER_S_PBEGIN
next_port_speeder_client = WGOP_USPEEDER_C_PBEGIN
next_port_balancer = WGOP_LB_PBEGIN
next_port_client = WGOP_UC_PBEGIN
udp2raw_config = {
"server": [],
"client": []
}
def add_server(self, port_required, password, speeder_info):
self.udp2raw_config["server"].append({
"port": port_required,
"password": get_sha256(password),
"speeder": speeder_info
})
def add_client(self, remote, password, port, speeder_info, demuxer_info, no_hash=False):
if port is None:
port = self.next_port_client
if demuxer_info:
self.next_port_client += demuxer_info["size"]
else:
self.next_port_client += 1
self.udp2raw_config["client"].append({
"remote": remote,
"password": password if no_hash else get_sha256(password),
"port": port,
"speeder": speeder_info,
"demuxer": demuxer_info
})
def new_server_speeder(self, port, ratio):
if port is None:
port = self.next_port_speeder_server
self.next_port_speeder_server += 1
return {
"port": port,
"ratio": ratio
}
def new_client_speeder(self, port, ratio):
if port is None:
port = self.next_port_speeder_client
self.next_port_speeder_client += 1
return {
"port": port,
"ratio": ratio
}
def new_demuxer(self, port, size):
if port is None:
port = self.next_port_balancer
self.next_port_balancer += 1
return {
"port": port,
"size": size
}

View File

@ -1,220 +0,0 @@
# -*- coding: utf-8 -*-
import os
import getpass
from wgop_common import load_config, save_config, get_randpass, get_quick_config
from wgop_common import UConfigController
config = load_config()
if config:
print("Valid config found. Creation of server is skipped.")
exit(0)
else:
print("No config found. Start creating interactively.")
print("====== Choose Role ======")
op_mode = input("What will this node act as? (C)lient [S]erver [M]ixed: ").strip().lower()
if not op_mode:
print("Default to client mode.")
op_mode = "c"
if op_mode not in ("c", "s", "m"):
print("Invalid node mode. Please try again.")
exit(1)
ucontrol = UConfigController()
if op_mode in ("s", "m"):
print("====== Configuring udp2raw server ======")
while True:
print("====== Adding UDP2RAW Server #{} ======".format(len(ucontrol.udp2raw_config["server"]) + 1))
while True:
udp_server_port = input("Please select an Internet-Facing port for incoming udp2raw connection: ").strip()
if not udp_server_port:
print("A udp2raw listen port is required. Try again.")
continue
break
while True:
udp_server_password = getpass.getpass('Tunnel Password: (Keep empty to generate one)').strip()
if not udp_server_password:
udp_server_password = get_randpass(15)
print("Generated Password: {}".format(udp_server_password))
break
if udp_server_password != getpass.getpass('Confirm Tunnel Password: ').strip():
print("Password mismatch. Try again.")
continue
break
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [y/N]: ").strip()
if is_enable_speeder and is_enable_speeder.lower() in ('y', 'yes'):
speeder_ratio = input("Enter UDP Speeder Ratio (default to 20:10. Use 2:4 for gaming usage): ").strip() or "20:10"
speeder_info = ucontrol.new_server_speeder(None, speeder_ratio)
else:
speeder_info = None
ucontrol.add_server(udp_server_port, udp_server_password, speeder_info)
if not input("Add more udp2raw server? (Keep empty to finish): ").strip():
break
if op_mode in ("c", "m"):
print("====== Configuring udp2raw client ======")
while True:
print("====== Adding UDP2RAW Client {} ======".format(len(ucontrol.udp2raw_config["client"]) + 1))
while True:
udp_server_address = input("Please input remote node internet-facing udp2raw ip:port : ").strip()
if not udp_server_address:
print("A udp2raw remote server information is required. Try again.")
continue
break
while True:
udp_server_password = getpass.getpass('Tunnel Password: ').strip()
if not udp_server_password:
print("A udp2raw tunnel password is required. Try again.")
continue
if udp_server_password != getpass.getpass('Confirm Tunnel Password: ').strip():
print("Password mismatch. Try again.")
continue
break
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [y/N]: ").strip()
if is_enable_speeder and is_enable_speeder.lower() in ('y', 'yes'):
speeder_ratio = input("Enter UDP Speeder Ratio (default to 20:10. Use 2:4 for gaming usage): ").strip() or "20:10"
speeder_info = ucontrol.new_client_speeder(None, speeder_ratio)
else:
speeder_info = None
is_enable_balance = input("Enable Load Balance? [y/N]: ").strip()
if is_enable_balance and is_enable_balance.lower() in ('y', 'yes'):
balance_count = input("Enter Balance Underlay Connection counts (default to 10): ").strip() or "10"
balance_count = int(balance_count)
if balance_count > 1:
balancer_info = ucontrol.new_demuxer(None, balance_count)
else:
print("[WARN] Only one target, skipped balancer creation.")
balancer_info = None
else:
balancer_info = None
ucontrol.add_client(udp_server_address, udp_server_password, None, speeder_info, balancer_info)
if not input("Add more udp2raw client? (Keep empty to finish)").strip():
break
wg_prik = os.getenv("WG_MYPRIK")
wg_pubk = os.getenv("WG_MYPUBK")
wg_mtu = "1000"
wg_public_ip = os.getenv("WG_PUBLICIP")
print('''
====== Your WireGuard Public Key ======
{}
======= Your Public IP Address ========
{}
=======================================
'''.format(wg_pubk, wg_public_ip))
ifname = input("Input new WireGuard interface name (wg0):").strip() or "wg0"
listen_port = input("Input new WireGuard listen port (51820): ").strip() or "51820"
while True:
ifip = input("Input WireGuard interface ip (Example: 10.0.0.1)\n> ").strip()
if not ifip:
print("You MUST set a valid WireGuard interface IP. Try Again.")
continue
break
print("Saving config...")
config = {
"version": 1,
"mode": op_mode,
"pubkey": wg_pubk,
"prikey": wg_prik,
"mtu": wg_mtu,
"interface": ifname,
"ip": ifip,
"listen": listen_port,
"peers": [],
"udp2raw": ucontrol.udp2raw_config
}
save_config(config)
# Display Quick Config
if op_mode in ("s", "m"):
print("===== Quick Import =====")
quicks = get_quick_config(config, wg_public_ip)
for quick_info in quicks:
print("Connect to this server via tunnel at port {}: (credential included)\n{}\n".format(quick_info["port"], quick_info["qcs"]))
# Configure Peer
while True:
print("====== Adding Peer {} ======".format(len(config["peers"]) + 1))
while True:
peer_pubk = input("Enter WireGuard Peer Public Key: ").strip()
if not peer_pubk:
print("A public key is required. Try Again.")
continue
break
while True:
peer_allowed = input("Enter WireGuard Peer AllowedIPs (CIDR, Example: 10.0.0.0/24)\n> ").strip()
if not peer_allowed:
print("Peer allowed ips required. Try Again.")
continue
break
if ucontrol.udp2raw_config["client"]:
print(">>> Choose from following udp2raw clients <<<")
for index, client_info in enumerate(ucontrol.udp2raw_config["client"]):
speeder_info = client_info["speeder"]
balancer_info = client_info["demuxer"]
print("[{}] {} {} {}".format(index + 1, client_info["remote"],
"SpeederRatio: {}".format(speeder_info["ratio"]) if speeder_info else "",
"Load-Balanced over {} tunnels".format(balancer_info["size"]) if balancer_info else ""
))
peer_endpoint = input("Enter WireGuard Peer Endpoint (ID from list, default to 1): ").strip() or "1"
peer_keepalive = input("Enter WireGuard Peer Keep Alive seconds (default to 30): ").strip() or "30"
else:
peer_endpoint = ""
peer_keepalive = ""
peer_name = input("Enter Peer name (optional): ").strip() or ""
config["peers"].append({
"pubkey": peer_pubk,
"allowed": peer_allowed,
"endpoint": peer_endpoint,
"keepalive": peer_keepalive,
"name": peer_name,
})
print("Saving config...")
save_config(config)
if not input("Add more peers? (Keep empty to finish)").strip():
break

View File

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
import os
from wgop_common import load_config, get_quick_config
config = load_config()
if not config:
print("[WARN] Config not found.")
exit(1)
quicks = get_quick_config(config, os.getenv("WG_PUBLICIP"))
if not quicks:
print("No server configured.")
exit(0)
print("===== Quick Import =====")
for quick_info in quicks:
print("Connect to this server via tunnel at port {}: (credential included)\n{}\n".format(quick_info["port"], quick_info["qcs"]))

View File

@ -1,195 +0,0 @@
# -*- coding: utf-8 -*-
import os
import uuid
from wgop_common import load_config, SimpleLogger
logger = SimpleLogger()
def write_tunnel_config(mode, listen_addr, remote_addr, password):
filename = "{}.conf".format(uuid.uuid4())
with open("local/tunnel/{}".format(filename), "w", encoding='utf-8') as f:
f.write('''
-{}
-l {}
-r {}
-k {}
--raw-mode faketcp
--fix-gro
-a
'''.format(mode, listen_addr, remote_addr, password))
return filename
tmux_path = os.getenv("TMUX_PATH")
config = load_config()
if not config:
logger.error("No valid config found.")
exit(1)
if "version" not in config or int(config["version"]) < 1:
logger.warn("[WARN] Legacy version of config found. This may cause issues.")
op_mode = config["mode"]
udp_clients = config["udp2raw"]["client"]
udp_servers = config["udp2raw"]["server"]
logger.info("Generating WireGuard config...")
with open("local/{}.conf".format(config["interface"]), "w", encoding='utf-8') as f:
f.write('''[Interface]
Address = {}
PrivateKey = {}
ListenPort = {}
MTU = {}
'''.format(config["ip"], config["prikey"], config["listen"], config["mtu"]))
# Generate PostUp
f.write('''PostUp={} new-session -s tunnel -d 'watch -n 1 --color WG_COLOR_MODE=always wg'
PostUp=sysctl net.core.default_qdisc=fq
PostUp=sysctl net.ipv4.tcp_congestion_control=bbr
'''.format(tmux_path))
if op_mode in ("s", "m"):
f.write("PostUp=sysctl net.ipv4.ip_forward=1\n")
current_dir = os.getcwd()
bin_tunnel = os.path.join(current_dir, "bin", "udp2raw_amd64")
bin_speeder = os.path.join(current_dir, "bin", "speederv2_amd64")
bin_demuxer = os.path.join(current_dir, "bin", "w2u")
cache_nb_config = []
cache_config = []
for client_info in udp_clients:
speeder_info = client_info["speeder"]
balancer_info = client_info["demuxer"]
if balancer_info:
# ... => Balancer => Tunnels
cache_nb_config.append("PostUp={} new-window -t tunnel -d '{} -f {} -l {} -t {} -s {}'".format(tmux_path, bin_demuxer, config["listen"], balancer_info["port"], client_info["port"], balancer_info["size"]))
if speeder_info:
if balancer_info:
# WG => Speeder => Balancer => Tunnels
cache_config.append("PostUp={} new-window -t tunnel -d '{} -c -l127.0.0.1:{} -r 127.0.0.1:{} -f{} --mode 0'".format(tmux_path, bin_speeder, speeder_info["port"], balancer_info["port"], speeder_info["ratio"]))
else:
# WG => Speeder => Tunnel
cache_config.append("PostUp={} new-window -t tunnel -d '{} -c -l127.0.0.1:{} -r 127.0.0.1:{} -f{} --mode 0'".format(tmux_path, bin_speeder, speeder_info["port"], client_info["port"], speeder_info["ratio"]))
if balancer_info:
# Generate multiple tunnels
for offset in range(balancer_info["size"]):
config_filename = write_tunnel_config("c", "127.0.0.1:{}".format(client_info["port"] + offset), client_info["remote"], client_info["password"])
filepath = os.path.join(current_dir, "local", "tunnel", config_filename)
cache_config.append("PostUp={} new-window -t tunnel -d '{} --conf-file {}'".format(tmux_path, bin_tunnel, filepath))
else:
config_filename = write_tunnel_config("c", "127.0.0.1:{}".format(client_info["port"]), client_info["remote"], client_info["password"])
filepath = os.path.join(current_dir, "local", "tunnel", config_filename)
cache_config.append("PostUp={} new-window -t tunnel -d '{} --conf-file {}'".format(tmux_path, bin_tunnel, filepath))
for server_info in udp_servers:
speeder_info = server_info["speeder"]
if speeder_info:
# RawTunnel => Speeder => WG
speeder = server_info["speeder"]
cache_config.append("PostUp={} new-window -t tunnel -d '{} -s -l127.0.0.1:{} -r 127.0.0.1:{} -f{} --mode 0'".format(tmux_path, bin_speeder, speeder["port"], config["listen"], speeder["ratio"]))
config_filename = write_tunnel_config("s", "0.0.0.0:{}".format(server_info["port"]), "127.0.0.1:{}".format(speeder["port"]), server_info["password"])
filepath = os.path.join(current_dir, "local", "tunnel", config_filename)
cache_config.append("PostUp={} new-window -t tunnel -d '{} --conf-file {}'".format(tmux_path, bin_tunnel, filepath))
else:
# RawTunnel => WG
config_filename = write_tunnel_config("s", "0.0.0.0:{}".format(server_info["port"]), "127.0.0.1:{}".format(config["listen"]), server_info["password"])
filepath = os.path.join(current_dir, "local", "tunnel", config_filename)
cache_config.append("PostUp={} new-window -t tunnel -d '{} --conf-file {}'".format(tmux_path, bin_tunnel, filepath))
# Add sleep interval
if cache_config:
for i in range(len(cache_config) - 1):
cache_config[i] = "{}; sleep 2".format(cache_config[i])
cache_config.append("")
f.write('\n'.join(cache_config))
if cache_nb_config:
cache_nb_config.append("")
f.write('\n'.join(cache_nb_config))
# Generate PostDown
f.write("PostDown={} kill-session -t tunnel\n".format(tmux_path))
for peer_info in config["peers"]:
f.write('''
[Peer]
PublicKey = {}
AllowedIPs = {}
'''.format(peer_info["pubkey"], peer_info["allowed"]))
if peer_info["endpoint"]:
client_info = udp_clients[int(peer_info["endpoint"]) - 1]
speeder_info = client_info["speeder"]
balancer_info = client_info["demuxer"]
if speeder_info:
# WG => Speeder => ...
f.write("Endpoint = 127.0.0.1:{}\n".format(speeder_info["port"]))
elif balancer_info:
# WG => Balancer => ...
f.write("Endpoint = 127.0.0.1:{}\n".format(balancer_info["port"]))
else:
# WG => ...
f.write("Endpoint = 127.0.0.1:{}\n".format(client_info["port"]))
if peer_info["keepalive"]:
f.write("PersistentKeepalive = {}\n".format(peer_info["keepalive"]))
os.system("chmod 600 local/{}.conf".format(config["interface"]))
logger.info("Generating start script...")
with open("start.sh", "w", encoding='utf-8') as f:
f.write('''#!/bin/bash
set -e
sudo cp local/{}.conf /etc/wireguard/
sudo wg-quick up {}
sudo tmux attach-session -t tunnel
'''.format(config["interface"], config["interface"]))
logger.info("Generating stop script...")
with open("stop.sh", "w", encoding='utf-8') as f:
f.write('''#!/bin/bash
set -x
sudo wg-quick down {}
'''.format(config["interface"]))
logger.info("Generating restart script...")
with open("restart.sh", "w", encoding='utf-8') as f:
f.write('''#!/bin/bash
set -x
./stop.sh
./start.sh
''')
logger.info("Generate reload script...")
with open("reload.sh", "w", encoding='utf-8') as f:
f.write('''#!/bin/bash
set -x
sudo cp local/{}.conf /etc/wireguard/
sudo -- bash -c "wg syncconf {} <(wg-quick strip {})"
'''.format(config["interface"], config["interface"], config["interface"]))
for peer_info in config["peers"]:
f.write("sudo ip -4 route add {} dev {}\n".format(peer_info["allowed"], config["interface"]))
logger.info('''[Done] Config generated. Before you run start.sh, besure to:
1. Disable SSH Server password login.
2. Enable UFW (or any other firewall)
Safety First.
''')

View File

@ -1,114 +0,0 @@
# -*- coding: utf-8 -*-
import os
from wgop_common import load_config, save_config, base64_to_json
from wgop_common import UConfigController
config = load_config()
if config:
print("Valid config found. Creation of server is skipped.")
exit(0)
print("No valid config found, creating a default one...")
ifname = input("Input new WireGuard interface name (wg0): ").strip() or "wg0"
listen_port = input("Input new WireGuard listen port (51820): ").strip() or "51820"
while True:
ifip = input("Input WireGuard interface ip (Example: 10.0.0.1)\n> ").strip()
if not ifip:
print("You MUST set a valid WireGuard interface IP. Try Again.")
continue
break
ucontrol = UConfigController()
paste_config = {}
while True:
paste_temp = input("Paste Quick Setup: ").strip()
if not paste_temp.startswith("#QCS#"):
print("Config not valid. Try again.")
continue
paste_config = base64_to_json(paste_temp.replace("#QCS#", ""))
print("Config imported. Server: {} with public key: {}{}".format(
paste_config["remote"], paste_config["pubkey"],
" and speeders enabled" if paste_config["ratio"] else ""))
break
if paste_config["ratio"]:
speeder_info = ucontrol.new_client_speeder(None, paste_config["ratio"])
else:
speeder_info = None
is_enable_balance = input("Enable Load Balance? [y/N]: ").strip()
if is_enable_balance and is_enable_balance.lower() in ('y', 'yes'):
balance_count = input("Enter Balance Underlay Connection counts (default to 10): ").strip() or "10"
balance_count = int(balance_count)
if balance_count > 1:
balancer_info = ucontrol.new_demuxer(None, balance_count)
else:
print("[WARN] Only one target, skipped balancer creation.")
balancer_info = None
else:
balancer_info = None
ucontrol.add_client(paste_config["remote"], paste_config["password"], None, speeder_info, balancer_info, no_hash=True)
if paste_config["allowed"]:
peer_allowed = input("Enter WireGuard Peer AllowedIPs (CIDR, Example: 10.0.0.0/24, default to {})\n> ".format(paste_config["allowed"])).strip()
if not peer_allowed:
peer_allowed = paste_config["allowed"]
else:
while True:
peer_allowed = input("Enter WireGuard Peer AllowedIPs (CIDR, Example: 10.0.0.0/24)\n> ").strip()
if not peer_allowed:
print("Peer allowed ips required. Try Again.")
continue
break
peer_keepalive = input("Enter WireGuard Peer Keep Alive seconds (default to 30): ").strip() or "30"
# Generate Config
config = {
"version": 1,
"mode": "c",
"prikey": os.getenv("WG_MYPRIK"),
"pubkey": os.getenv("WG_MYPUBK"),
"mtu": "1000",
"interface": ifname,
"ip": ifip,
"listen": listen_port,
"peers": [{
"pubkey": paste_config["pubkey"],
"allowed": peer_allowed,
"endpoint": "1",
"keepalive": peer_keepalive
}],
"udp2raw": ucontrol.udp2raw_config
}
print("Saving config...")
save_config(config)
print('''
====== Your WireGuard Public Key ======
{}
====== Your WireGuard IP Address ======
{}
=======================================
'''.format(os.getenv("WG_MYPUBK"), ifip))