""" Network tools. - Wireguard VPN - OpenVPN - Tailscale client - DHCP server (isc-dhcp-server / kea) - DNS forwarder (unbound / dnsmasq) """ from . import register, Generator, Field from . import bash_header, quote, bool_str, yes # ========================== WireGuard ========================== class WireGuard(Generator): id = "wireguard" title = "WireGuard VPN" category = "network" icon = "🔒" tags = ["wireguard", "vpn", "wg"] description = "部署 WireGuard VPN server,可生成客户端配置。" fields = [ Field("server_private_key", "Server Private Key", "password", default="", help="留空将自动生成 (使用 wg genkey)。"), Field("server_public_key", "Server Public Key", "text", default="", help="留空将自动从 private key 派生。"), Field("listen_port", "Listen 端口", "number", default="51820", min_=1, max_=65535), Field("interface", "网卡接口", "text", default="eth0"), Field("vpn_subnet", "VPN 子网 CIDR", "text", default="10.0.0.0/24"), Field("server_vpn_ip", "Server VPN IP", "text", default="10.0.0.1/24"), Field("peers", "客户端 Peer 列表", "textarea", default="client1\nclient2", help="每行一个 client name,会为每个生成密钥对。"), Field("peer_dns", "客户端 DNS", "text", default="1.1.1.1, 8.8.8.8"), ] def render(self, p): sk = p.get("server_private_key", "").strip() pk = p.get("server_public_key", "").strip() port = str(p.get("listen_port", "51820")) iface = p.get("interface", "eth0") subnet = p.get("vpn_subnet", "10.0.0.0/24") sip = p.get("server_vpn_ip", "10.0.0.1/24") peers = [p_.strip() for p_ in p.get("peers", "").splitlines() if p_.strip()] dns = p.get("peer_dns", "1.1.1.1, 8.8.8.8") out = [bash_header(self.title)] out.append('log "Installing WireGuard..."') out.append('PKG_INSTALL wireguard qrencode') out.append('') # server keypair if not sk: out.append('wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub') else: out.append('mkdir -p /etc/wireguard && echo "' + sk + '" > /etc/wireguard/server.key') out.append('wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub') if pk: out.append('echo "' + pk + '" > /etc/wireguard/server.pub') out.append('chmod 600 /etc/wireguard/server.key') out.append('') # generate peer configs out.append('mkdir -p /etc/wireguard/clients') for i, name in enumerate(peers, start=2): ip = f'10.0.0.{i}/32' out.append('wg genkey | tee /etc/wireguard/clients/' + name + '.key | wg pubkey > /etc/wireguard/clients/' + name + '.pub') out.append('chmod 600 /etc/wireguard/clients/' + name + '.key') # server conf out.append('cat > /etc/wireguard/wg0.conf <> /etc/sysctl.d/99-wireguard.conf && sysctl -p /etc/sysctl.d/99-wireguard.conf') out.append('systemctl enable --now wg-quick@wg0') # build client confs for i, name in enumerate(peers, start=2): ip = f'10.0.0.{i}/32' out.append('SERVER_PUB=$(cat /etc/wireguard/server.pub)') out.append('CLIENT_PRIV=$(cat /etc/wireguard/clients/' + name + '.key)') out.append('cat > /etc/wireguard/clients/' + name + '.conf < /etc/dnsmasq.conf < /etc/openvpn/server.conf <> /etc/sysctl.d/99-openvpn.conf && sysctl -p') for i in range(1, n + 1): cn = f'client{i}' out.append('cd /etc/openvpn/easy-rsa && ./easyrsa gen-req ' + cn + ' nopass') out.append('cd /etc/openvpn/easy-rsa && ./easyrsa sign-req client ' + cn + ' <<< "yes"') out.append('cat > /etc/openvpn/' + cn + '.ovpn <\n$(cat /etc/openvpn/ca.crt)\n\n\n$(cat /etc/openvpn/easy-rsa/pki/issued/' + cn + '.crt)\n\n\n$(cat /etc/openvpn/easy-rsa/pki/private/' + cn + '.key)\n\n\n$(cat /etc/openvpn/ta.key)\n\nkey-direction 1\nOVPN_EOF') return "\n".join(out) + "\n" for _g in [WireGuard, Tailscale, Dnsmasq, OpenVPN]: register(_g())