diff options
| author | diogo464 <[email protected]> | 2025-07-18 18:46:55 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-07-18 18:46:55 +0100 |
| commit | 75ccbd675c22fb3275c5763518c3b97819db4c53 (patch) | |
| tree | 1ff2a44abcac884875f80a44a569681e0f2d7a7d /src/setup.rs | |
init
Diffstat (limited to 'src/setup.rs')
| -rw-r--r-- | src/setup.rs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/setup.rs b/src/setup.rs new file mode 100644 index 0000000..e7d454c --- /dev/null +++ b/src/setup.rs | |||
| @@ -0,0 +1,212 @@ | |||
| 1 | use std::net::{IpAddr, SocketAddr}; | ||
| 2 | |||
| 3 | use ipnet::IpNet; | ||
| 4 | use netlink_packet_wireguard::{ | ||
| 5 | constants::{AF_INET, AF_INET6, WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REPLACE_ALLOWEDIPS}, | ||
| 6 | nlas::{WgAllowedIp, WgAllowedIpAttrs, WgDeviceAttrs, WgPeer, WgPeerAttrs}, | ||
| 7 | Wireguard, WireguardCmd, | ||
| 8 | }; | ||
| 9 | |||
| 10 | use super::Key; | ||
| 11 | |||
| 12 | #[derive(Debug)] | ||
| 13 | pub struct PeerDescriptor { | ||
| 14 | pub(super) public_key: Key, | ||
| 15 | pub(super) preshared_key: Option<Key>, | ||
| 16 | pub(super) endpoint: Option<SocketAddr>, | ||
| 17 | pub(super) keepalive: Option<u16>, | ||
| 18 | pub(super) allowed_ips: Option<Vec<IpNet>>, | ||
| 19 | } | ||
| 20 | |||
| 21 | impl PeerDescriptor { | ||
| 22 | pub fn new(public_key: Key) -> Self { | ||
| 23 | Self { | ||
| 24 | public_key, | ||
| 25 | preshared_key: None, | ||
| 26 | endpoint: None, | ||
| 27 | keepalive: None, | ||
| 28 | allowed_ips: None, | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | pub fn preshared_key_optional(mut self, preshared_key: Option<Key>) -> Self { | ||
| 33 | self.preshared_key = preshared_key; | ||
| 34 | self | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn preshared_key(mut self, preshared_key: Key) -> Self { | ||
| 38 | self.preshared_key = Some(preshared_key); | ||
| 39 | self | ||
| 40 | } | ||
| 41 | |||
| 42 | pub fn endpoint_optional(mut self, endpoint: Option<SocketAddr>) -> Self { | ||
| 43 | self.endpoint = endpoint; | ||
| 44 | self | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn endpoint(mut self, endpoint: SocketAddr) -> Self { | ||
| 48 | self.endpoint = Some(endpoint); | ||
| 49 | self | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn keepalive_optional(mut self, keepalive: Option<u16>) -> Self { | ||
| 53 | self.keepalive = keepalive; | ||
| 54 | self | ||
| 55 | } | ||
| 56 | |||
| 57 | pub fn keepalive(mut self, keepalive: u16) -> Self { | ||
| 58 | self.keepalive = Some(keepalive); | ||
| 59 | self | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn allowed_ip_optional(self, allowed_ip: Option<IpNet>) -> Self { | ||
| 63 | if let Some(allowed_ip) = allowed_ip { | ||
| 64 | self.allowed_ip(allowed_ip) | ||
| 65 | } else { | ||
| 66 | self | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | pub fn allowed_ip(mut self, allowed_ip: IpNet) -> Self { | ||
| 71 | let mut allowed_ips = self.allowed_ips.take().unwrap_or_default(); | ||
| 72 | allowed_ips.push(allowed_ip); | ||
| 73 | self.allowed_ips = Some(allowed_ips); | ||
| 74 | self | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn allowed_ips_optional(self, allowed_ips: Option<Vec<IpNet>>) -> Self { | ||
| 78 | if let Some(allowed_ips) = allowed_ips { | ||
| 79 | self.allowed_ips(allowed_ips) | ||
| 80 | } else { | ||
| 81 | self | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | pub fn allowed_ips(mut self, allowed_ips: Vec<IpNet>) -> Self { | ||
| 86 | self.allowed_ips = Some(allowed_ips); | ||
| 87 | self | ||
| 88 | } | ||
| 89 | |||
| 90 | pub(super) fn into_wireguard(self) -> WgPeer { | ||
| 91 | let mut nlas = Vec::new(); | ||
| 92 | nlas.push(WgPeerAttrs::PublicKey(self.public_key.into_array())); | ||
| 93 | nlas.extend( | ||
| 94 | self.preshared_key | ||
| 95 | .map(|key| WgPeerAttrs::PresharedKey(key.into_array())), | ||
| 96 | ); | ||
| 97 | nlas.extend(self.endpoint.map(WgPeerAttrs::Endpoint)); | ||
| 98 | nlas.extend(self.keepalive.map(WgPeerAttrs::PersistentKeepalive)); | ||
| 99 | nlas.extend(self.allowed_ips.map(|allowed_ips| { | ||
| 100 | WgPeerAttrs::AllowedIps(allowed_ips.into_iter().map(ipnet_to_wg).collect()) | ||
| 101 | })); | ||
| 102 | nlas.push(WgPeerAttrs::Flags(WGPEER_F_REPLACE_ALLOWEDIPS)); | ||
| 103 | WgPeer(nlas) | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | #[derive(Debug)] | ||
| 108 | pub struct DeviceDescriptor { | ||
| 109 | pub(super) addresses: Vec<IpNet>, | ||
| 110 | pub(super) private_key: Option<Key>, | ||
| 111 | pub(super) listen_port: Option<u16>, | ||
| 112 | pub(super) fwmark: Option<u32>, | ||
| 113 | pub(super) peers: Option<Vec<PeerDescriptor>>, | ||
| 114 | } | ||
| 115 | |||
| 116 | impl Default for DeviceDescriptor { | ||
| 117 | fn default() -> Self { | ||
| 118 | Self::new() | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | impl DeviceDescriptor { | ||
| 123 | pub fn new() -> Self { | ||
| 124 | Self { | ||
| 125 | addresses: Vec::default(), | ||
| 126 | private_key: None, | ||
| 127 | listen_port: None, | ||
| 128 | fwmark: None, | ||
| 129 | peers: None, | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | pub fn address(mut self, address: IpNet) -> Self { | ||
| 134 | self.addresses.push(address); | ||
| 135 | self | ||
| 136 | } | ||
| 137 | |||
| 138 | pub fn addresses(mut self, addresses: impl IntoIterator<Item = IpNet>) -> Self { | ||
| 139 | self.addresses.extend(addresses); | ||
| 140 | self | ||
| 141 | } | ||
| 142 | |||
| 143 | pub fn private_key(mut self, key: Key) -> Self { | ||
| 144 | self.private_key = Some(key); | ||
| 145 | self | ||
| 146 | } | ||
| 147 | |||
| 148 | pub fn listen_port(mut self, port: u16) -> Self { | ||
| 149 | self.listen_port = Some(port); | ||
| 150 | self | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn listen_port_optional(mut self, port: Option<u16>) -> Self { | ||
| 154 | self.listen_port = port; | ||
| 155 | self | ||
| 156 | } | ||
| 157 | |||
| 158 | pub fn fwmark(mut self, fwmark: u32) -> Self { | ||
| 159 | self.fwmark = Some(fwmark); | ||
| 160 | self | ||
| 161 | } | ||
| 162 | |||
| 163 | pub fn peer(mut self, peer: PeerDescriptor) -> Self { | ||
| 164 | let mut p = self.peers.take().unwrap_or_default(); | ||
| 165 | p.push(peer); | ||
| 166 | self.peers = Some(p); | ||
| 167 | self | ||
| 168 | } | ||
| 169 | |||
| 170 | pub fn peers(mut self, peers: impl IntoIterator<Item = PeerDescriptor>) -> Self { | ||
| 171 | let mut p = self.peers.take().unwrap_or_default(); | ||
| 172 | p.extend(peers); | ||
| 173 | self.peers = Some(p); | ||
| 174 | self | ||
| 175 | } | ||
| 176 | |||
| 177 | pub(super) fn into_wireguard(self, device_name: String) -> Wireguard { | ||
| 178 | let mut nlas = Vec::new(); | ||
| 179 | nlas.push(WgDeviceAttrs::IfName(device_name)); | ||
| 180 | nlas.extend( | ||
| 181 | self.private_key | ||
| 182 | .map(|key| WgDeviceAttrs::PrivateKey(key.into_array())), | ||
| 183 | ); | ||
| 184 | nlas.extend(self.listen_port.map(WgDeviceAttrs::ListenPort)); | ||
| 185 | nlas.extend(self.fwmark.map(WgDeviceAttrs::Fwmark)); | ||
| 186 | nlas.extend(self.peers.map(|peers| { | ||
| 187 | WgDeviceAttrs::Peers( | ||
| 188 | peers | ||
| 189 | .into_iter() | ||
| 190 | .map(PeerDescriptor::into_wireguard) | ||
| 191 | .collect(), | ||
| 192 | ) | ||
| 193 | })); | ||
| 194 | nlas.push(WgDeviceAttrs::Flags(WGDEVICE_F_REPLACE_PEERS)); | ||
| 195 | |||
| 196 | Wireguard { | ||
| 197 | cmd: WireguardCmd::SetDevice, | ||
| 198 | nlas, | ||
| 199 | } | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | fn ipnet_to_wg(net: IpNet) -> WgAllowedIp { | ||
| 204 | let mut nlas = Vec::default(); | ||
| 205 | nlas.push(WgAllowedIpAttrs::Cidr(net.prefix_len())); | ||
| 206 | nlas.push(WgAllowedIpAttrs::IpAddr(net.addr())); | ||
| 207 | match net.addr() { | ||
| 208 | IpAddr::V4(_) => nlas.push(WgAllowedIpAttrs::Family(AF_INET)), | ||
| 209 | IpAddr::V6(_) => nlas.push(WgAllowedIpAttrs::Family(AF_INET6)), | ||
| 210 | } | ||
| 211 | WgAllowedIp(nlas) | ||
| 212 | } | ||
