vpn: assign an IPv6 subnet instead of a single address
We are limited by the size of IPv4 pool (/18), so why not give everyone an IPv4-internetful of IPv6 addresses.
This commit is contained in:
parent
85714f83b9
commit
a8abf580f9
|
@ -108,7 +108,7 @@ def save_config():
|
|||
wireguard = db.read('wireguard')
|
||||
for ip, key in wireguard.items():
|
||||
ip4 = [f'{ip}/32']
|
||||
ip6 = [f'{key["ip6"]}/128'] if key.get('ip6') else None
|
||||
ip6 = [f'{key["ip6"]}'] if key.get('ip6') else None
|
||||
for network in user_networks.get(key.get('user', ''), ()):
|
||||
if group := network_group(network):
|
||||
ipset_add(ipsets, group, ip4, ip6)
|
||||
|
|
17
web/vpn.py
17
web/vpn.py
|
@ -29,6 +29,19 @@ def list():
|
|||
@blueprint.route('/new', methods=('POST',))
|
||||
@flask_login.login_required
|
||||
def new():
|
||||
# Each key is associated with a new IPv4 address from the pool settings['wg_net'].
|
||||
# Each key gets an IPv6 subnet depending on the amount of surplus addresses available.
|
||||
# For wg_net 10.10.0.0/18 and wg_net6 1234:5678:90ab:cdef::/64,
|
||||
# the key for 10.10.0.10/32 would get 1234:5678:90ab:cdef:a::/80.
|
||||
def ipv4to6(net4, ip4, net6):
|
||||
# Calculate the address and prefix length for the assigned IPv6 network.
|
||||
len4 = (net4.max_prefixlen - net4.prefixlen)
|
||||
len6 = (net6.max_prefixlen - net6.prefixlen)
|
||||
# Make sure the network address ends at a colon. Wastes some addresses but IPv6.
|
||||
assigned = (len6 - len4) - (len6 - len4) % 16
|
||||
ip6 = (net6.network_address + (index<<assigned)).compressed
|
||||
return ip6 + '/' + str(net6.max_prefixlen - assigned)
|
||||
|
||||
pubkey = flask.request.json.get('pubkey', '')
|
||||
if not re.match(wgkey_regex, pubkey):
|
||||
return flask.Response('invalid key', status=400, mimetype='text/plain')
|
||||
|
@ -38,14 +51,14 @@ def new():
|
|||
text=True, capture_output=True, shell=True).stdout.strip()
|
||||
|
||||
host = ipaddress.ip_interface(settings.get('wg_net', '10.0.0.1/24'))
|
||||
ip6 = None
|
||||
with db.locked():
|
||||
# Find a free address for the new key.
|
||||
keys = db.read('wireguard')
|
||||
ip6 = None
|
||||
for index, ip in enumerate(host.network.hosts(), start=1):
|
||||
if ip != host.ip and str(ip) not in keys:
|
||||
if wg_net6 := settings.get('wg_net6'):
|
||||
ip6 = (ipaddress.ip_interface(wg_net6) + index).ip
|
||||
ip6 = ipv4to6(host.network, ip, ipaddress.ip_interface(wg_net6).network)
|
||||
break
|
||||
else:
|
||||
return flask.Response('no more available IP addresses', status=500, mimetype='text/plain')
|
||||
|
|
Loading…
Reference in a new issue