wireguard_conf/models/builders.rs
1use either::Either;
2use ipnet::Ipv4Net;
3
4use crate::prelude::*;
5
6/// Builder, that used for creating [`Interface`]s.
7///
8/// # Examples
9///
10/// ```
11/// use wireguard_conf::prelude::*;
12///
13/// let server_private_key = PrivateKey::random();
14///
15/// let interface = InterfaceBuilder::new()
16/// .address("10.0.0.1/24".parse().unwrap())
17/// .listen_port(6969)
18/// .private_key(server_private_key.clone())
19/// .set_dns(vec!["8.8.8.8".to_string(), "8.8.4.4".to_string()])
20/// .endpoint("vpn.example.com".to_string())
21/// // .add_peer(some_peer)
22/// .build();
23///
24/// assert_eq!(interface.address, "10.0.0.1/24".parse().unwrap());
25/// assert_eq!(interface.listen_port, Some(6969));
26/// assert_eq!(interface.private_key, server_private_key);
27/// assert_eq!(interface.dns, vec!["8.8.8.8", "8.8.4.4"]);
28/// assert_eq!(interface.endpoint, Some("vpn.example.com".to_string()));
29/// ```
30#[must_use]
31#[derive(Default)]
32pub struct InterfaceBuilder {
33 address: Ipv4Net,
34 listen_port: Option<u16>,
35 private_key: Option<PrivateKey>,
36 dns: Vec<String>,
37 endpoint: Option<String>,
38 peers: Vec<Peer>,
39
40 #[cfg(feature = "amneziawg")]
41 #[cfg_attr(docsrs, doc(cfg(feature = "amneziawg")))]
42 amnezia_settings: Option<AmneziaSettings>,
43}
44
45impl InterfaceBuilder {
46 pub fn new() -> InterfaceBuilder {
47 InterfaceBuilder::default()
48 }
49
50 /// Set the address.
51 ///
52 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#address)
53 pub fn address(mut self, address: Ipv4Net) -> Self {
54 self.address = address;
55 self
56 }
57
58 /// Set the listen port.
59 ///
60 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#listenport)
61 pub fn listen_port(mut self, listen_port: u16) -> Self {
62 self.listen_port = Some(listen_port);
63 self
64 }
65
66 /// Set the private key.
67 ///
68 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#privatekey)
69 pub fn private_key(mut self, private_key: PrivateKey) -> Self {
70 self.private_key = Some(private_key);
71 self
72 }
73
74 /// Set the DNS servers array.
75 ///
76 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#dns-2)
77 pub fn set_dns(mut self, dns: Vec<String>) -> Self {
78 self.dns = dns;
79 self
80 }
81
82 /// Add DNS server.
83 ///
84 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#dns-2)
85 pub fn add_dns(mut self, dns: String) -> Self {
86 self.dns.push(dns);
87 self
88 }
89
90 /// Set the endpoint.
91 ///
92 /// # Note
93 ///
94 /// - In interface's config this set `# Name = ...`
95 /// - If you export interface via [`Interface::as_peer()`], exported peer will have this
96 /// `Peer.endpoint`
97 ///
98 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#listenport)
99 pub fn endpoint(mut self, endpoint: String) -> Self {
100 self.endpoint = Some(endpoint);
101 self
102 }
103
104 /// Set the Peers array.
105 ///
106 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#peer)
107 pub fn set_peers(mut self, peers: Vec<Peer>) -> Self {
108 self.peers = peers;
109 self
110 }
111
112 /// Add peer.
113 ///
114 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#peer)
115 pub fn add_peer(mut self, peer: Peer) -> Self {
116 self.peers.push(peer);
117 self
118 }
119
120 /// Sets AmneziaWG obfuscation values.
121 ///
122 /// [AmneziaWG Docs](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration)
123 #[cfg(feature = "amneziawg")]
124 #[cfg_attr(docsrs, doc(cfg(feature = "amneziawg")))]
125 pub fn amnezia_settings(mut self, amnezia_settings: AmneziaSettings) -> Self {
126 self.amnezia_settings = Some(amnezia_settings);
127 self
128 }
129
130 /// Creates [`Interface`].
131 pub fn build(self) -> Interface {
132 Interface {
133 address: self.address,
134 listen_port: self.listen_port,
135 private_key: self.private_key.unwrap_or_else(PrivateKey::random),
136 dns: self.dns,
137
138 #[cfg(feature = "amneziawg")]
139 amnezia_settings: None,
140
141 endpoint: self.endpoint,
142 peers: self.peers,
143 }
144 }
145}
146
147/// Builder, that used for creating [`Peer`]s.
148///
149/// # Examples
150///
151/// ```
152/// use wireguard_conf::prelude::*;
153/// use either::Either;
154///
155/// let client_private_key = PrivateKey::random();
156///
157/// let peer = PeerBuilder::new()
158/// .endpoint("public.client.example.com".to_string())
159/// .add_allowed_ip("10.0.0.2/32".parse().unwrap())
160/// .private_key(client_private_key.clone())
161/// // if you don't want to generate interface from peer, you can provide public key
162/// // instead of private_key:
163/// // .public_key(client_public_key)
164/// .build();
165///
166/// assert_eq!(peer.endpoint, Some("public.client.example.com".to_string()));
167/// assert_eq!(peer.allowed_ips, vec!["10.0.0.2/32".parse().unwrap()]);
168/// assert_eq!(peer.key, Either::Left(client_private_key));
169/// ```
170#[must_use]
171#[derive(Default)]
172pub struct PeerBuilder {
173 endpoint: Option<String>,
174 allowed_ips: Vec<Ipv4Net>,
175 key: Option<Either<PrivateKey, PublicKey>>,
176
177 #[cfg(feature = "amneziawg")]
178 #[cfg_attr(docsrs, doc(cfg(feature = "amneziawg")))]
179 amnezia_settings: Option<AmneziaSettings>,
180}
181
182impl PeerBuilder {
183 pub fn new() -> PeerBuilder {
184 PeerBuilder::default()
185 }
186
187 /// Sets endpoint.
188 ///
189 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#endpoint)
190 pub fn endpoint(mut self, endpoint: String) -> PeerBuilder {
191 self.endpoint = Some(endpoint);
192 self
193 }
194
195 /// Sets Allowed IPs array.
196 ///
197 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#allowedips)
198 pub fn set_allowed_ips(mut self, ip: Vec<Ipv4Net>) -> PeerBuilder {
199 self.allowed_ips = ip;
200 self
201 }
202
203 /// Adds allowed IP.
204 ///
205 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#allowedips)
206 pub fn add_allowed_ip(mut self, ip: Ipv4Net) -> PeerBuilder {
207 self.allowed_ips.push(ip);
208 self
209 }
210
211 /// Sets private key.
212 ///
213 /// # Note
214 ///
215 /// If you set private key (instead of public key), you can generate [`Interface`] from [`Peer`] (see [`Peer::as_interface()`]).
216 ///
217 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#publickey)
218 pub fn private_key(mut self, private_key: PrivateKey) -> PeerBuilder {
219 self.key = Some(Either::Left(private_key));
220 self
221 }
222
223 /// Sets public key.
224 ///
225 /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#publickey)
226 pub fn public_key(mut self, public_key: PublicKey) -> PeerBuilder {
227 self.key = Some(Either::Right(public_key));
228 self
229 }
230
231 /// Sets AmneziaWG obfuscation values.
232 ///
233 /// [AmneziaWG Docs](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration)
234 #[cfg(feature = "amneziawg")]
235 #[cfg_attr(docsrs, doc(cfg(feature = "amneziawg")))]
236 pub fn amnezia_settings(mut self, amnezia_settings: AmneziaSettings) -> Self {
237 self.amnezia_settings = Some(amnezia_settings);
238 self
239 }
240
241 /// Creates [`Peer`].
242 pub fn build(self) -> Peer {
243 let key = self
244 .key
245 .unwrap_or_else(|| Either::Left(PrivateKey::random()));
246
247 Peer {
248 endpoint: self.endpoint,
249 allowed_ips: self.allowed_ips,
250 key,
251
252 #[cfg(feature = "amneziawg")]
253 amnezia_settings: self.amnezia_settings,
254 }
255 }
256}