bundles/wireguard: rework metadata.py
Some checks failed
bundlewrap/pipeline/head There was a failure building this commit
Some checks failed
bundlewrap/pipeline/head There was a failure building this commit
This commit is contained in:
parent
b679f568eb
commit
6e423c24fb
7 changed files with 155 additions and 64 deletions
|
@ -1,8 +0,0 @@
|
||||||
[Match]
|
|
||||||
Name=wg0
|
|
||||||
|
|
||||||
[Network]
|
|
||||||
Address=${my_ip}
|
|
||||||
|
|
||||||
[Route]
|
|
||||||
Destination=${network}
|
|
|
@ -1,21 +1,16 @@
|
||||||
|
from ipaddress import ip_network
|
||||||
|
|
||||||
assert node.has_bundle('systemd-networkd')
|
assert node.has_bundle('systemd-networkd')
|
||||||
|
|
||||||
|
network = ip_network(node.metadata['wireguard']['my_ip'], strict=False)
|
||||||
|
|
||||||
files = {
|
files = {
|
||||||
'/etc/systemd/network/99-wg0.netdev': {
|
'/etc/systemd/network/wg0.netdev': {
|
||||||
'source': 'wg0.netdev',
|
|
||||||
'content_type': 'mako',
|
'content_type': 'mako',
|
||||||
'context': node.metadata['wireguard'],
|
'context': {
|
||||||
'needs': {
|
'network': f'{network.network_address}/{network.prefixlen}',
|
||||||
'pkg_apt:wireguard',
|
**node.metadata['wireguard'],
|
||||||
},
|
},
|
||||||
'triggers': {
|
|
||||||
'svc_systemd:systemd-networkd:restart',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'/etc/systemd/network/99-wg0.network': {
|
|
||||||
'source': 'wg0.network',
|
|
||||||
'content_type': 'mako',
|
|
||||||
'context': node.metadata['wireguard'],
|
|
||||||
'needs': {
|
'needs': {
|
||||||
'pkg_apt:wireguard',
|
'pkg_apt:wireguard',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
from ipaddress import ip_network
|
||||||
|
|
||||||
|
from bundlewrap.exceptions import NoSuchNode
|
||||||
from bundlewrap.metadata import atomic
|
from bundlewrap.metadata import atomic
|
||||||
|
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
'apt': {
|
'apt': {
|
||||||
'packages': {
|
'packages': {
|
||||||
|
@ -16,10 +20,10 @@ defaults = {
|
||||||
},
|
},
|
||||||
'iptables': {
|
'iptables': {
|
||||||
'bundle_rules': {
|
'bundle_rules': {
|
||||||
'wireguard': [
|
'wireguard': {
|
||||||
'iptables_both -A FORWARD -i wg0 -j ACCEPT',
|
'iptables_both -A FORWARD -i wg0 -j ACCEPT',
|
||||||
'iptables_both -A FORWARD -o wg0 -j ACCEPT',
|
'iptables_both -A FORWARD -o wg0 -j ACCEPT',
|
||||||
],
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'wireguard': {
|
'wireguard': {
|
||||||
|
@ -29,51 +33,77 @@ defaults = {
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'wireguard/network',
|
'wireguard/peers',
|
||||||
)
|
)
|
||||||
def get_wireguard_network_from_server(metadata):
|
def peer_psks(metadata):
|
||||||
# FIXME This will break if more than one node sets 'wireguard/network'
|
peers = {}
|
||||||
for rnode in repo.nodes:
|
|
||||||
if not rnode.has_bundle('wireguard'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if node.name in rnode.metadata.get('wireguard/peers', {}).keys():
|
for peer_name in metadata.get('wireguard/peers', {}):
|
||||||
network = rnode.metadata.get('wireguard/network', None)
|
peers[peer_name] = {}
|
||||||
|
|
||||||
if network:
|
if node.name < peer_name:
|
||||||
return {
|
peers[peer_name] = {
|
||||||
'wireguard': {
|
'psk': repo.vault.random_bytes_as_base64_for(f'{node.name} wireguard {peer_name}'),
|
||||||
'network': network,
|
}
|
||||||
},
|
else:
|
||||||
}
|
peers[peer_name] = {
|
||||||
|
'psk': repo.vault.random_bytes_as_base64_for(f'{peer_name} wireguard {node.name}'),
|
||||||
|
}
|
||||||
|
|
||||||
return {}
|
return {
|
||||||
|
'wireguard': {
|
||||||
|
'peers': peers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'wireguard/peers',
|
'wireguard/peers',
|
||||||
)
|
)
|
||||||
def get_my_wireguard_peers(metadata):
|
def peer_pubkeys(metadata):
|
||||||
peers = {}
|
peers = {}
|
||||||
|
|
||||||
for rnode in repo.nodes:
|
for peer_name in metadata.get('wireguard/peers', {}):
|
||||||
if not rnode.has_bundle('wireguard'):
|
try:
|
||||||
|
rnode = repo.get_node(peer_name)
|
||||||
|
except NoSuchNode:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if node.name in rnode.metadata.get('wireguard/peers', {}).keys():
|
peers[peer_name] = {
|
||||||
peers[rnode.name] = {
|
'pubkey': repo.libs.keys.get_pubkey_from_privkey(
|
||||||
'pubkey': repo.libs.keys.get_pubkey_from_privkey(repo, f'{node.name} wireguard {rnode.name}', rnode.metadata.get('wireguard/privatekey')),
|
repo,
|
||||||
'psk': rnode.metadata.get('wireguard/psk', metadata.get('wireguard/psk', None)),
|
f'{rnode.name} wireguard pubkey',
|
||||||
}
|
rnode.metadata.get('wireguard/privatekey'),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
if not rnode.metadata.get(f'wireguard/peers/{node.name}/do_not_initiate_a_connection_from_your_side', False):
|
return {
|
||||||
peers[rnode.name]['endpoint'] = f'{rnode.hostname}:51820'
|
'wireguard': {
|
||||||
|
'peers': peers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
peers[rnode.name]['ips'] = rnode.metadata.get('wireguard/subnets', set())
|
|
||||||
|
|
||||||
your_ip = rnode.metadata.get('wireguard/my_ip', None)
|
@metadata_reactor.provides(
|
||||||
if your_ip:
|
'wireguard/peers',
|
||||||
peers[rnode.name]['ips'].add(your_ip)
|
)
|
||||||
|
def peer_ips_and_endpoints(metadata):
|
||||||
|
peers = {}
|
||||||
|
|
||||||
|
for peer_name in metadata.get('wireguard/peers', {}):
|
||||||
|
try:
|
||||||
|
rnode = repo.get_node(peer_name)
|
||||||
|
except NoSuchNode:
|
||||||
|
continue
|
||||||
|
|
||||||
|
ips = rnode.metadata.get('wireguard/subnets', set())
|
||||||
|
ips.add(rnode.metadata.get('wireguard/my_ip').split('/')[0])
|
||||||
|
ips = repo.libs.tools.remove_more_specific_subnets(ips)
|
||||||
|
|
||||||
|
peers[rnode.name] = {
|
||||||
|
'endpoint': '{}:51820'.format(rnode.metadata.get('wireguard/external_hostname', rnode.hostname)),
|
||||||
|
'ips': ips,
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'wireguard': {
|
'wireguard': {
|
||||||
|
@ -109,10 +139,63 @@ def icinga2(metadata):
|
||||||
'iptables/port_rules',
|
'iptables/port_rules',
|
||||||
)
|
)
|
||||||
def iptables(metadata):
|
def iptables(metadata):
|
||||||
|
sources = set(metadata.get('wireguard/restrict-to', set()))
|
||||||
|
for peer_name in metadata.get('wireguard/peers'):
|
||||||
|
try:
|
||||||
|
rnode = repo.get_node(peer_name)
|
||||||
|
except NoSuchNode: # roadwarrior
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
sources.add(peer_name)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'iptables': {
|
'iptables': {
|
||||||
'port_rules': {
|
'port_rules': {
|
||||||
'51820/udp': atomic(metadata.get('wireguard/restrict-to', set(metadata.get('wireguard/peers', {}).keys()))),
|
'51820/udp': atomic(sources),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@metadata_reactor.provides(
|
||||||
|
'interfaces/wg0/ips',
|
||||||
|
)
|
||||||
|
def interface_ips(metadata):
|
||||||
|
return {
|
||||||
|
'interfaces': {
|
||||||
|
'wg0': {
|
||||||
|
'ips': {
|
||||||
|
metadata.get('wireguard/my_ip'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@metadata_reactor.provides(
|
||||||
|
'interfaces/wg0/routes',
|
||||||
|
)
|
||||||
|
def routes(metadata):
|
||||||
|
network = ip_network(metadata.get('wireguard/my_ip'), strict=False)
|
||||||
|
ips = {
|
||||||
|
f'{network.network_address}/{network.prefixlen}',
|
||||||
|
}
|
||||||
|
routes = {}
|
||||||
|
|
||||||
|
for _, peer_config in metadata.get('wireguard/peers', {}).items():
|
||||||
|
for ip in peer_config['ips']:
|
||||||
|
ips.add(ip)
|
||||||
|
|
||||||
|
if '0.0.0.0/0' in ips:
|
||||||
|
ips.remove('0.0.0.0/0')
|
||||||
|
|
||||||
|
for ip in repo.libs.tools.remove_more_specific_subnets(ips):
|
||||||
|
routes[ip] = {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'interfaces': {
|
||||||
|
'wg0': {
|
||||||
|
'routes': routes,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,3 +55,26 @@ def resolve_identifier(repo, identifier):
|
||||||
ip_dict['ipv6'].add(ip)
|
ip_dict['ipv6'].add(ip)
|
||||||
|
|
||||||
return ip_dict
|
return ip_dict
|
||||||
|
|
||||||
|
|
||||||
|
def remove_more_specific_subnets(input_subnets) -> list:
|
||||||
|
final_subnets = []
|
||||||
|
|
||||||
|
for subnet in sorted(input_subnets):
|
||||||
|
source = ip_network(subnet)
|
||||||
|
|
||||||
|
if not source in final_subnets:
|
||||||
|
subnet_found = False
|
||||||
|
|
||||||
|
for dest_subnet in final_subnets:
|
||||||
|
if source.subnet_of(dest_subnet):
|
||||||
|
subnet_found = True
|
||||||
|
|
||||||
|
if not subnet_found:
|
||||||
|
final_subnets.append(source)
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for net in final_subnets:
|
||||||
|
out.append(str(net))
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
|
@ -172,17 +172,15 @@ nodes['home.router'] = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'wireguard': {
|
'wireguard': {
|
||||||
# TODO autogenerate?
|
'external_hostname': 'franzi-home.kunbox.net', # Set via DynDNS
|
||||||
'my_ip': '172.19.136.2/32',
|
'my_ip': '172.19.136.2/22',
|
||||||
|
'peers': {
|
||||||
|
'ovh.wireguard': {},
|
||||||
|
},
|
||||||
'subnets': {
|
'subnets': {
|
||||||
'172.19.138.0/24',
|
'172.19.138.0/24',
|
||||||
'172.19.139.0/24',
|
'172.19.139.0/24',
|
||||||
},
|
},
|
||||||
'peers': {
|
|
||||||
'ovh.wireguard': {
|
|
||||||
'do_not_initiate_a_connection_from_your_side': True,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ nodes['ovh.icinga2'] = {
|
||||||
'service_filter': '"checks_with_sms" in service.groups'
|
'service_filter': '"checks_with_sms" in service.groups'
|
||||||
},
|
},
|
||||||
'wireguard': {
|
'wireguard': {
|
||||||
'my_ip': '172.19.136.3/32',
|
'my_ip': '172.19.136.3/22',
|
||||||
'peers': {
|
'peers': {
|
||||||
'ovh.wireguard': {},
|
'ovh.wireguard': {},
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,10 +24,10 @@ nodes['ovh.wireguard'] = {
|
||||||
'ram': 2,
|
'ram': 2,
|
||||||
},
|
},
|
||||||
'wireguard': {
|
'wireguard': {
|
||||||
'network': '172.19.136.0/22',
|
'my_ip': '172.19.136.1/22',
|
||||||
'my_ip': '172.19.136.1/32',
|
|
||||||
'psk': vault.random_bytes_as_base64_for('ovh.icinga2 wireguard psk'),
|
|
||||||
'peers': {
|
'peers': {
|
||||||
|
'ovh.icinga2': {},
|
||||||
|
'home.router': {},
|
||||||
'kunsi-oneplus3': {
|
'kunsi-oneplus3': {
|
||||||
'ips': {
|
'ips': {
|
||||||
'172.19.136.100/32',
|
'172.19.136.100/32',
|
||||||
|
|
Loading…
Reference in a new issue