2021-04-01 14:27:31 +00:00
|
|
|
from ipaddress import ip_network
|
|
|
|
|
|
|
|
from bundlewrap.exceptions import NoSuchNode
|
2021-03-21 14:26:29 +00:00
|
|
|
from bundlewrap.metadata import atomic
|
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
|
2020-11-21 14:38:38 +00:00
|
|
|
defaults = {
|
|
|
|
'apt': {
|
|
|
|
'packages': {
|
|
|
|
'wireguard': {},
|
|
|
|
},
|
|
|
|
'repos': {
|
|
|
|
'backports': {
|
|
|
|
'install_gpg_key': False, # default debian signing key
|
|
|
|
'items': [
|
|
|
|
'deb http://deb.debian.org/debian {os_release}-backports main',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'iptables': {
|
|
|
|
'bundle_rules': {
|
2021-04-01 15:13:24 +00:00
|
|
|
'wireguard': [
|
2020-11-21 14:38:38 +00:00
|
|
|
'iptables_both -A FORWARD -i wg0 -j ACCEPT',
|
2021-03-15 08:00:35 +00:00
|
|
|
'iptables_both -A FORWARD -o wg0 -j ACCEPT',
|
2021-04-01 15:13:24 +00:00
|
|
|
],
|
2020-11-21 14:38:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
'wireguard': {
|
|
|
|
'privatekey': repo.libs.keys.gen_privkey(repo, f'{node.name} wireguard privatekey'),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-04-23 17:31:28 +00:00
|
|
|
if node.has_bundle('telegraf'):
|
|
|
|
defaults['telegraf'] = {
|
|
|
|
'input_plugins': {
|
|
|
|
'builtin': {
|
|
|
|
'wireguard': [{}],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-21 14:38:38 +00:00
|
|
|
|
2021-01-07 17:44:38 +00:00
|
|
|
@metadata_reactor.provides(
|
2021-04-01 14:27:31 +00:00
|
|
|
'wireguard/peers',
|
2021-01-07 17:44:38 +00:00
|
|
|
)
|
2021-04-01 14:27:31 +00:00
|
|
|
def peer_psks(metadata):
|
|
|
|
peers = {}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
for peer_name in metadata.get('wireguard/peers', {}):
|
|
|
|
peers[peer_name] = {}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
if node.name < peer_name:
|
|
|
|
peers[peer_name] = {
|
|
|
|
'psk': repo.vault.random_bytes_as_base64_for(f'{node.name} wireguard {peer_name}'),
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
peers[peer_name] = {
|
|
|
|
'psk': repo.vault.random_bytes_as_base64_for(f'{peer_name} wireguard {node.name}'),
|
|
|
|
}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
return {
|
|
|
|
'wireguard': {
|
|
|
|
'peers': peers,
|
|
|
|
},
|
|
|
|
}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
|
|
|
|
2021-01-07 17:44:38 +00:00
|
|
|
@metadata_reactor.provides(
|
|
|
|
'wireguard/peers',
|
|
|
|
)
|
2021-04-01 14:27:31 +00:00
|
|
|
def peer_pubkeys(metadata):
|
2020-11-21 14:38:38 +00:00
|
|
|
peers = {}
|
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
for peer_name in metadata.get('wireguard/peers', {}):
|
|
|
|
try:
|
|
|
|
rnode = repo.get_node(peer_name)
|
|
|
|
except NoSuchNode:
|
2020-11-21 14:38:38 +00:00
|
|
|
continue
|
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
peers[peer_name] = {
|
|
|
|
'pubkey': repo.libs.keys.get_pubkey_from_privkey(
|
|
|
|
repo,
|
|
|
|
f'{rnode.name} wireguard pubkey',
|
|
|
|
rnode.metadata.get('wireguard/privatekey'),
|
|
|
|
),
|
|
|
|
}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
return {
|
|
|
|
'wireguard': {
|
|
|
|
'peers': peers,
|
|
|
|
},
|
|
|
|
}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
|
|
|
|
2021-04-01 14:27:31 +00:00
|
|
|
@metadata_reactor.provides(
|
|
|
|
'wireguard/peers',
|
|
|
|
)
|
|
|
|
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,
|
|
|
|
}
|
2020-11-21 14:38:38 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
'wireguard': {
|
|
|
|
'peers': peers,
|
|
|
|
},
|
|
|
|
}
|
2020-11-30 05:43:35 +00:00
|
|
|
|
|
|
|
|
2021-01-07 17:44:38 +00:00
|
|
|
@metadata_reactor.provides(
|
|
|
|
'icinga2_api/wireguard/services',
|
|
|
|
)
|
2020-11-30 05:43:35 +00:00
|
|
|
def icinga2(metadata):
|
|
|
|
services = {}
|
|
|
|
|
|
|
|
for peer, config in metadata.get('wireguard/peers', {}).items():
|
2021-02-14 20:35:37 +00:00
|
|
|
if config.get('exclude_from_monitoring', False):
|
|
|
|
continue
|
|
|
|
|
2020-11-30 05:43:35 +00:00
|
|
|
services[f'WIREGUARD CONNECTION {peer}'] = {
|
2020-12-10 15:39:26 +00:00
|
|
|
'command_on_monitored_host': config['pubkey'].format_into('sudo /usr/local/share/icinga/plugins/check_wireguard_connected wg0 {}'),
|
2020-11-30 05:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
'icinga2_api': {
|
|
|
|
'wireguard': {
|
|
|
|
'services': services,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2021-03-21 14:26:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
@metadata_reactor.provides(
|
|
|
|
'iptables/port_rules',
|
|
|
|
)
|
|
|
|
def iptables(metadata):
|
2021-04-01 14:27:31 +00:00
|
|
|
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)
|
|
|
|
|
2021-03-21 14:26:29 +00:00
|
|
|
return {
|
|
|
|
'iptables': {
|
|
|
|
'port_rules': {
|
2021-04-01 14:27:31 +00:00
|
|
|
'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,
|
2021-03-21 14:26:29 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|