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