wireguard_control/config.rs
1use crate::{
2 device::{AllowedIp, PeerConfig},
3 key::Key,
4};
5
6use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
7
8/// Builds and represents a single peer in a WireGuard interface configuration.
9///
10/// Note that if a peer with that public key already exists on the interface,
11/// the settings specified here will be applied _on top_ of the existing settings,
12/// similarly to interface-wide settings.
13///
14/// If this is not what you want, use [`DeviceConfigBuilder::replace_peers`](DeviceConfigBuilder::replace_peers)
15/// to replace all peer settings on the interface, or use
16/// [`DeviceConfigBuilder::remove_peer_by_key`](DeviceConfigBuilder::remove_peer_by_key) first
17/// to remove the peer from the interface, and then apply a second configuration to re-add it.
18///
19/// # Example
20/// ```rust
21/// # use wireguard_control::*;
22/// # use std::net::AddrParseError;
23/// # fn try_main() -> Result<(), AddrParseError> {
24/// let peer_keypair = KeyPair::generate();
25///
26/// // create a new peer and allow it to connect from 192.168.1.2
27/// let peer = PeerConfigBuilder::new(&peer_keypair.public)
28/// .replace_allowed_ips()
29/// .add_allowed_ip("192.168.1.2".parse()?, 32);
30///
31/// // update our existing configuration with the new peer
32/// DeviceUpdate::new().add_peer(peer).apply(&"wg-example".parse().unwrap(), Backend::Userspace);
33///
34/// println!("Send these keys to your peer: {:#?}", peer_keypair);
35///
36/// # Ok(())
37/// # }
38/// # fn main() { try_main(); }
39/// ```
40#[derive(Debug, PartialEq, Eq, Clone)]
41pub struct PeerConfigBuilder {
42 pub(crate) public_key: Key,
43 pub(crate) preshared_key: Option<Key>,
44 pub(crate) endpoint: Option<SocketAddr>,
45 pub(crate) persistent_keepalive_interval: Option<u16>,
46 pub(crate) allowed_ips: Vec<AllowedIp>,
47 pub(crate) replace_allowed_ips: bool,
48 pub(crate) remove_me: bool,
49}
50
51impl PeerConfigBuilder {
52 /// Creates a new `PeerConfigBuilder` that does nothing when applied.
53 pub fn new(public_key: &Key) -> Self {
54 PeerConfigBuilder {
55 public_key: public_key.clone(),
56 preshared_key: None,
57 endpoint: None,
58 persistent_keepalive_interval: None,
59 allowed_ips: vec![],
60 replace_allowed_ips: false,
61 remove_me: false,
62 }
63 }
64
65 pub fn into_peer_config(self) -> PeerConfig {
66 PeerConfig {
67 public_key: self.public_key,
68 preshared_key: self.preshared_key,
69 endpoint: self.endpoint,
70 persistent_keepalive_interval: self.persistent_keepalive_interval,
71 allowed_ips: self.allowed_ips,
72 }
73 }
74
75 /// The public key used in this builder.
76 pub fn public_key(&self) -> &Key {
77 &self.public_key
78 }
79
80 /// Creates a `PeerConfigBuilder` from a [`PeerConfig`](PeerConfig).
81 ///
82 /// This is mostly a convenience method for cases when you want to copy
83 /// some or most of the existing peer configuration to a new configuration.
84 ///
85 /// This returns a `PeerConfigBuilder`, so you can still call any methods
86 /// you need to override the imported settings.
87 pub fn from_peer_config(config: PeerConfig) -> Self {
88 let mut builder = Self::new(&config.public_key);
89 if let Some(k) = config.preshared_key {
90 builder = builder.set_preshared_key(k);
91 }
92 if let Some(e) = config.endpoint {
93 builder = builder.set_endpoint(e);
94 }
95 if let Some(k) = config.persistent_keepalive_interval {
96 builder = builder.set_persistent_keepalive_interval(k);
97 }
98 builder
99 .replace_allowed_ips()
100 .add_allowed_ips(&config.allowed_ips)
101 }
102
103 /// Specifies a preshared key to be set for this peer.
104 #[must_use]
105 pub fn set_preshared_key(mut self, key: Key) -> Self {
106 self.preshared_key = Some(key);
107 self
108 }
109
110 /// Specifies that this peer's preshared key should be unset.
111 #[must_use]
112 pub fn unset_preshared_key(self) -> Self {
113 self.set_preshared_key(Key::zero())
114 }
115
116 /// Specifies an exact endpoint that this peer should be allowed to connect from.
117 #[must_use]
118 pub fn set_endpoint(mut self, address: SocketAddr) -> Self {
119 self.endpoint = Some(address);
120 self
121 }
122
123 /// Specifies the interval between keepalive packets to be sent to this peer.
124 #[must_use]
125 pub fn set_persistent_keepalive_interval(mut self, interval: u16) -> Self {
126 self.persistent_keepalive_interval = Some(interval);
127 self
128 }
129
130 /// Specifies that this peer does not require keepalive packets.
131 #[must_use]
132 pub fn unset_persistent_keepalive(self) -> Self {
133 self.set_persistent_keepalive_interval(0)
134 }
135
136 /// Specifies an IP address this peer will be allowed to connect from/to.
137 ///
138 /// See [`AllowedIp`](AllowedIp) for details. This method can be called
139 /// more than once, and all IP addresses will be added to the configuration.
140 #[must_use]
141 pub fn add_allowed_ip(mut self, address: IpAddr, cidr: u8) -> Self {
142 self.allowed_ips.push(AllowedIp { address, cidr });
143 self
144 }
145
146 /// Specifies multiple IP addresses this peer will be allowed to connect from/to.
147 ///
148 /// See [`AllowedIp`](AllowedIp) for details. This method can be called
149 /// more than once, and all IP addresses will be added to the configuration.
150 #[must_use]
151 pub fn add_allowed_ips(mut self, ips: &[AllowedIp]) -> Self {
152 self.allowed_ips.extend_from_slice(ips);
153 self
154 }
155
156 /// Specifies this peer should be allowed to connect to all IP addresses.
157 ///
158 /// This is a convenience method for cases when you want to connect to a server
159 /// that all traffic should be routed through.
160 #[must_use]
161 pub fn allow_all_ips(self) -> Self {
162 self.add_allowed_ip(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
163 .add_allowed_ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 0)
164 }
165
166 /// Specifies that the allowed IP addresses in this configuration should replace
167 /// the existing configuration of the interface, not be appended to it.
168 #[must_use]
169 pub fn replace_allowed_ips(mut self) -> Self {
170 self.replace_allowed_ips = true;
171 self
172 }
173
174 /// Mark peer for removal from interface.
175 #[must_use]
176 pub fn remove(mut self) -> Self {
177 self.remove_me = true;
178 self
179 }
180}