mirror of
https://github.com/Kiritow/wg-ops.git
synced 2024-03-22 13:11:37 +08:00
Major Update
Fix: generated stop.sh cannot be executed. Add: restart script. Add: use getpass for password input. Add: Paste & Go: Exchange config with ease
This commit is contained in:
parent
7318a9d634
commit
895db3a3b9
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
||||||
bin/
|
bin/
|
||||||
local/
|
local/
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
*.json
|
*.json
|
||||||
*.conf
|
*.conf
|
||||||
start.sh
|
start.sh
|
||||||
|
|
67
tool_common.py
Normal file
67
tool_common.py
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
|
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: {}".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'))
|
149
tool_create.py
149
tool_create.py
|
@ -1,16 +1,19 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import os
|
import os
|
||||||
import json
|
import getpass
|
||||||
import traceback
|
from tool_common import load_config, save_config, SimpleLogger, json_to_base64
|
||||||
|
|
||||||
try:
|
|
||||||
with open("local/config.json") as f:
|
logger = SimpleLogger()
|
||||||
content = f.read()
|
|
||||||
config = json.loads(content)
|
config = load_config()
|
||||||
print("[WARN] Found a valid config. Creation of server is skipped.")
|
if config:
|
||||||
|
logger.warn("Valid config found. Creation of server is skipped.")
|
||||||
exit(0)
|
exit(0)
|
||||||
except Exception:
|
else:
|
||||||
print(traceback.format_exc())
|
logger.info("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()
|
op_mode = input("What will this node act as? (C)lient [S]erver [M]ixed: ").strip().lower()
|
||||||
if not op_mode:
|
if not op_mode:
|
||||||
|
@ -40,12 +43,17 @@ if op_mode in ("s", "m"):
|
||||||
break
|
break
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
udp_server_password = input("Please input udp2raw tunnel password: ").strip()
|
udp_server_password = getpass.getpass('Tunnel Password: ').strip()
|
||||||
if not udp_server_password:
|
if not udp_server_password:
|
||||||
print("A udp2raw tunnel password is required. Try again.")
|
print("For security reasons, a udp2raw tunnel password is required. Try again.")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if udp_server_password != getpass.getpass('Confirm Tunnel Password: ').strip():
|
||||||
|
print("Password mismatch. Try again.")
|
||||||
|
continue
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [Y/n]: ").strip()
|
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [Y/n]: ").strip()
|
||||||
if not is_enable_speeder or is_enable_speeder.lower() in ('y', 'yes'):
|
if not is_enable_speeder or 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()
|
speeder_ratio = input("Enter UDP Speeder Ratio (default to 20:10. Use 2:4 for gaming usage): ").strip()
|
||||||
|
@ -65,7 +73,7 @@ if op_mode in ("s", "m"):
|
||||||
"speeder": speeder_info
|
"speeder": speeder_info
|
||||||
})
|
})
|
||||||
|
|
||||||
if not input("Add more udp2raw server? (Keep empty to finish)").strip():
|
if not input("Add more udp2raw server? (Keep empty to finish): ").strip():
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,10 +91,15 @@ if op_mode in ("c", "m"):
|
||||||
break
|
break
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
udp_server_password = input("Please input udp2raw tunnel password: ").strip()
|
udp_server_password = getpass.getpass('Tunnel Password: ').strip()
|
||||||
if not udp_server_password:
|
if not udp_server_password:
|
||||||
print("A udp2raw tunnel password is required. Try again.")
|
print("A udp2raw tunnel password is required. Try again.")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if udp_server_password != getpass.getpass('Confirm Tunnel Password: ').strip():
|
||||||
|
print("Password mismatch. Try again.")
|
||||||
|
continue
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [Y/n]: ").strip()
|
is_enable_speeder = input("Enable UDP Speeder for this tunnel? [Y/n]: ").strip()
|
||||||
|
@ -135,51 +148,14 @@ print('''
|
||||||
ifname = input("Input new wireguard interface name (wg0):").strip() or "wg0"
|
ifname = input("Input new wireguard interface name (wg0):").strip() or "wg0"
|
||||||
listen_port = input("Input new wireguard listen port (51820): ").strip() or "51820"
|
listen_port = input("Input new wireguard listen port (51820): ").strip() or "51820"
|
||||||
while True:
|
while True:
|
||||||
ifip = input("Input wireguard interface ip (Example: 10.0.0.1): ").strip()
|
ifip = input("Input wireguard interface ip (Example: 10.0.0.1)\n> ").strip()
|
||||||
if not ifip:
|
if not ifip:
|
||||||
print("You MUST set a valid wireguard interface IP. Try Again.")
|
print("You MUST set a valid wireguard interface IP. Try Again.")
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
peers = []
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print("====== Adding Peer {} ======".format(len(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): ").strip()
|
|
||||||
if not peer_allowed:
|
|
||||||
print("Peer allowed ips required. Try Again.")
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
|
|
||||||
print(">>> Choose from following udp2raw clients <<<")
|
|
||||||
for index, client_info in enumerate(udp2raw_config["client"]):
|
|
||||||
print("[{}] UDP2Raw Tunnel to Remote {}".format(index + 1, client_info["remote"]))
|
|
||||||
|
|
||||||
peer_endpoint = input("Enter Wireguard Peer Endpoint (ID from tunnel list, keep empty on server side): ").strip()
|
|
||||||
if peer_endpoint:
|
|
||||||
peer_keepalive = input("Enter Wireguard Peer Keep Alive seconds: ").strip()
|
|
||||||
else:
|
|
||||||
peer_keepalive = ""
|
|
||||||
|
|
||||||
peers.append({
|
|
||||||
"pubkey": peer_pubk,
|
|
||||||
"allowed": peer_allowed,
|
|
||||||
"endpoint": peer_endpoint,
|
|
||||||
"keepalive": peer_keepalive
|
|
||||||
})
|
|
||||||
|
|
||||||
if not input("Add more peers? (Keep empty to finish)").strip():
|
|
||||||
break
|
|
||||||
|
|
||||||
print("Saving to local config...")
|
|
||||||
|
|
||||||
|
print("Saving config...")
|
||||||
config = {
|
config = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"mode": op_mode,
|
"mode": op_mode,
|
||||||
|
@ -189,9 +165,70 @@ config = {
|
||||||
"interface": ifname,
|
"interface": ifname,
|
||||||
"ip": ifip,
|
"ip": ifip,
|
||||||
"listen": listen_port,
|
"listen": listen_port,
|
||||||
"peers": peers,
|
"peers": [],
|
||||||
"udp2raw": udp2raw_config
|
"udp2raw": udp2raw_config
|
||||||
}
|
}
|
||||||
|
save_config(config)
|
||||||
|
|
||||||
with open("local/config.json", "w") as f:
|
|
||||||
f.write(json.dumps(config, ensure_ascii=False))
|
if op_mode in ("s", "m"):
|
||||||
|
print("===== Quick Import =====")
|
||||||
|
for info in udp2raw_config["server"]:
|
||||||
|
target_config = {
|
||||||
|
"udp2raw": {
|
||||||
|
"client": [{
|
||||||
|
"remote": "{}:{}".format(wg_public_ip, info["port"]),
|
||||||
|
"password": info["password"],
|
||||||
|
"port": "",
|
||||||
|
"speeder": info["speeder"]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"pubkey": wg_pubk
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Connect to this server via tunnel at port {}: (credential included) \n".format(info["port"]))
|
||||||
|
print(" {}\n".format(json_to_base64(target_config)))
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
print(">>> Choose from following udp2raw clients <<<")
|
||||||
|
if config["udp2raw"]["client"]:
|
||||||
|
for index, client_info in enumerate(config["udp2raw"]["client"]):
|
||||||
|
print("[{}] UDP2Raw Tunnel to Remote {}".format(index + 1, client_info["remote"]))
|
||||||
|
else:
|
||||||
|
print(" no client ")
|
||||||
|
|
||||||
|
peer_endpoint = input("Enter Wireguard Peer Endpoint (ID from tunnel list, keep empty on server side): ").strip()
|
||||||
|
if peer_endpoint:
|
||||||
|
peer_keepalive = input("Enter Wireguard Peer Keep Alive seconds (default to 30): ").strip() or "30"
|
||||||
|
else:
|
||||||
|
peer_keepalive = "30"
|
||||||
|
|
||||||
|
config["peers"].append({
|
||||||
|
"pubkey": peer_pubk,
|
||||||
|
"allowed": peer_allowed,
|
||||||
|
"endpoint": peer_endpoint,
|
||||||
|
"keepalive": peer_keepalive
|
||||||
|
})
|
||||||
|
|
||||||
|
print("Saving config...")
|
||||||
|
save_config(config)
|
||||||
|
|
||||||
|
if not input("Add more peers? (Keep empty to finish)").strip():
|
||||||
|
break
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import os
|
import os
|
||||||
import json
|
from tool_common import load_config, SimpleLogger
|
||||||
import traceback
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("local/config.json") as f:
|
logger = SimpleLogger()
|
||||||
content = f.read()
|
|
||||||
config = json.loads(content)
|
|
||||||
except Exception:
|
config = load_config()
|
||||||
print(traceback.format_exc())
|
if not config:
|
||||||
print("[ERROR] No valid config found.")
|
logger.error("No valid config found.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
if "version" not in config or int(config["version"]) < 1:
|
if "version" not in config or int(config["version"]) < 1:
|
||||||
print("[WARN] Legacy version of config found. This may cause issues.")
|
logger.warn("[WARN] Legacy version of config found. This may cause issues.")
|
||||||
|
|
||||||
|
|
||||||
op_mode = config["mode"]
|
op_mode = config["mode"]
|
||||||
|
@ -21,7 +21,7 @@ udp_clients = config["udp2raw"]["client"]
|
||||||
udp_servers = config["udp2raw"]["server"]
|
udp_servers = config["udp2raw"]["server"]
|
||||||
|
|
||||||
|
|
||||||
print("Generating wireguard config...")
|
logger.info("Generating wireguard config...")
|
||||||
with open("local/{}.conf".format(config["interface"]), "w", encoding='utf-8') as f:
|
with open("local/{}.conf".format(config["interface"]), "w", encoding='utf-8') as f:
|
||||||
f.write('''[Interface]
|
f.write('''[Interface]
|
||||||
Address = {}
|
Address = {}
|
||||||
|
@ -48,7 +48,7 @@ AllowedIPs = {}
|
||||||
|
|
||||||
os.system("chmod 600 {}.conf".format(config["interface"]))
|
os.system("chmod 600 {}.conf".format(config["interface"]))
|
||||||
|
|
||||||
print("Generating start script...")
|
logger.info("Generating start script...")
|
||||||
with open("start.sh", "w", encoding='utf-8') as f:
|
with open("start.sh", "w", encoding='utf-8') as f:
|
||||||
f.write('''#!/bin/bash
|
f.write('''#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
@ -86,7 +86,7 @@ tmux attach-session -t tunnel
|
||||||
'''.format(config["interface"]))
|
'''.format(config["interface"]))
|
||||||
|
|
||||||
|
|
||||||
print("Generating stop script...")
|
logger.info("Generating stop script...")
|
||||||
with open("stop.sh", "w", encoding='utf-8') as f:
|
with open("stop.sh", "w", encoding='utf-8') as f:
|
||||||
f.write('''#!/bin/bash
|
f.write('''#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
@ -95,8 +95,20 @@ wg-quick down {}
|
||||||
tmux kill-session -t tunnel
|
tmux kill-session -t tunnel
|
||||||
'''.format(config["interface"]))
|
'''.format(config["interface"]))
|
||||||
|
|
||||||
|
os.system("chmod +x stop.sh")
|
||||||
|
|
||||||
print('''[OK] Config generated. Before you run start.sh, besure to:
|
|
||||||
|
logger.info("Generating restart script...")
|
||||||
|
with open("restart.sh", "w", encoding='utf-8') as f:
|
||||||
|
f.write('''#!/bin/bash
|
||||||
|
set -e
|
||||||
|
./stop.sh && ./start.sh
|
||||||
|
''')
|
||||||
|
|
||||||
|
os.system("chmod +x restart.sh")
|
||||||
|
|
||||||
|
|
||||||
|
logger.info('''[Done] Config generated. Before you run start.sh, besure to:
|
||||||
1. Disable SSH Server password login.
|
1. Disable SSH Server password login.
|
||||||
2. Enable UFW (or any other firewall)
|
2. Enable UFW (or any other firewall)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user