Skip to content

Instantly share code, notes, and snippets.

@shimarin
Last active December 22, 2021 01:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimarin/11652af3853dd32641c376b4e76f0bfd to your computer and use it in GitHub Desktop.
Save shimarin/11652af3853dd32641c376b4e76f0bfd to your computer and use it in GitHub Desktop.
Python script to build VPN config files for wireguard gateay server
#!/usr/bin/python
import argparse,ipaddress,subprocess,re
import qrcode
def generate_privkey():
return subprocess.check_output(["wg","genkey"]).decode("UTF-8").strip()
def get_pubkey(privkey):
return subprocess.check_output(["wg","pubkey"], input=privkey.encode("UTF-8")).decode("UTF-8").strip()
def octets(ipv4address):
i = int(ipv4address)
return (i >> 24, i >> 16 & 0xff, i >> 8 & 0xff, i & 0xff)
def main(global_v4_address, private_v4_address_start, private_v4_address_end, endpoint, port, mtu, conf_format, route_v4, route_v6, dns=None, privkey=None):
global_v4_address_in_octets = octets(global_v4_address)
if privkey is None: privkey = generate_privkey()
pubkey = get_pubkey(privkey)
if route_v4 == 'all': route_v4 = "0.0.0.0/0"
elif route_v4 == 'nolocal': route_v4 = "1.0.0.0/8, 2.0.0.0/8, 3.0.0.0/8, 4.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4"
if route_v6 == 'all': route_v6 = "::/0"
elif route_v6 == 'nolocal': route_v6 = "2000::/3"
allowedips = []
if route_v4 is not None: allowedips.append(route_v4)
if route_v6 is not None: allowedips.append(route_v6)
with open("wg0.conf", "w") as f:
print("[Interface]", file=f)
print("ListenPort=%d" % port, file=f)
print("MTU=%d" % mtu, file=f)
print("PrivateKey=%s" % privkey, file=f)
print("", file=f)
for i in range(int(private_v4_address_start),int(private_v4_address_end) + 1):
peer_privkey = generate_privkey()
peer_ipv4_address = ipaddress.IPv4Address(i)
peer_ipv4_address_in_octets = octets(peer_ipv4_address)
peer_ipv6_address = "fd%02x:%d:%d:%d:%d:%d:%d:%d" % (global_v4_address_in_octets[0], global_v4_address_in_octets[1], global_v4_address_in_octets[2], global_v4_address_in_octets[3], peer_ipv4_address_in_octets[0], peer_ipv4_address_in_octets[1], peer_ipv4_address_in_octets[2], peer_ipv4_address_in_octets[3])
print("[peer]", file=f)
print("PublicKey=%s" % get_pubkey(peer_privkey), file=f)
print("AllowedIPs=%s/32,%s/128" % (peer_ipv4_address, peer_ipv6_address), file=f)
print("", file=f)
peer_conf = conf_format.format(peer_ipv4_address_in_octets[0], peer_ipv4_address_in_octets[1], peer_ipv4_address_in_octets[2], peer_ipv4_address_in_octets[3])
with open(peer_conf, "w") as f2:
print("[Interface]", file=f2)
print("Address=%s/32,%s/128" % (peer_ipv4_address, peer_ipv6_address), file=f2)
print("PrivateKey=%s" % peer_privkey, file=f2)
if dns is not None: print("DNS=%s" % dns, file=f2)
print("", file=f2)
print("[peer]", file=f2)
print("PublicKey=%s" % pubkey, file=f2)
if len(allowedips) > 0:
print("AllowedIPs=%s" % (",".join(allowedips)), file=f2)
print("Endpoint=%s:%d" % (endpoint, port), file=f2)
print("PersistentKeepalive=25", file=f2)
with open(peer_conf) as f2:
qrcode.make(f2.read()).save(re.sub('\\.conf$', '.png', peer_conf))
print("Done.")
print("# for IPv4")
print("iptables -t nat -A POSTROUTING -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -j MASQUERADE")
print("iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu")
print("# for IPv6")
print("ip6tables -t nat -A POSTROUTING -s fc00::/7 -j MASQUERADE")
print("ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu")
print("# sysctl.conf")
print("net.ipv4.ip_forward=1")
print("net.ipv6.conf.default.forwarding=1")
print("net.ipv6.conf.all.forwarding=1")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=51820, help="WireGuard listen port")
parser.add_argument("--mtu", type=int, default=1280, help="Interface MTU")
parser.add_argument("--dns", help="DNS server to make peers use")
parser.add_argument("--privkey", default=None, help="Endpoint private Key(default: generate)")
parser.add_argument("--route-v4", default=None, help="AllowedIPs for IPv4. 'all' for all, 'nolocal' = for local addresses")
parser.add_argument("--route-v6", default=None, help="AllowedIPs for IPv6. 'all' for all, 'nolocal' = for local addresses")
parser.add_argument("--conf-format", default="wg-{0:03d}-{1:03d}-{2:03d}-{3:03d}.conf", help="conf filename format for peers")
parser.add_argument("global_v4_address")
parser.add_argument("private_v4_address_start")
parser.add_argument("private_v4_address_end")
parser.add_argument("endpoint")
args = parser.parse_args()
global_v4_address = ipaddress.IPv4Address(args.global_v4_address)
private_v4_address_start = ipaddress.IPv4Address(args.private_v4_address_start)
private_v4_address_end = ipaddress.IPv4Address(args.private_v4_address_end)
main(global_v4_address, private_v4_address_start, private_v4_address_end, args.endpoint, args.port, args.mtu, args.conf_format, args.route_v4, args.route_v6, args.dns, args.privkey)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment