1use std::{
9 fmt,
10 net::{SocketAddr, SocketAddrV4, SocketAddrV6},
11};
12
13#[derive(PartialEq, Debug)]
14pub enum ProxyProtocolHeader {
15 V1(HeaderV1),
16 V2(HeaderV2),
17}
18
19impl ProxyProtocolHeader {
20 pub fn into_bytes(&self) -> Vec<u8> {
22 match *self {
23 ProxyProtocolHeader::V1(ref header) => header.into_bytes(),
24 ProxyProtocolHeader::V2(ref header) => header.into_bytes(),
25 }
26 }
27}
28
29#[derive(Debug, PartialEq, Eq)]
31pub enum ProtocolSupportedV1 {
32 TCP4, TCP6, UNKNOWN, }
36
37impl fmt::Display for ProtocolSupportedV1 {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 match *self {
40 ProtocolSupportedV1::TCP4 => write!(f, "TCP4"),
41 ProtocolSupportedV1::TCP6 => write!(f, "TCP6"),
42 ProtocolSupportedV1::UNKNOWN => write!(f, "UNKNOWN"),
43 }
44 }
45}
46
47#[derive(Debug, PartialEq, Eq)]
56pub struct HeaderV1 {
57 pub protocol: ProtocolSupportedV1,
58 pub addr_src: SocketAddr,
59 pub addr_dst: SocketAddr,
60}
61
62const PROXY_PROTO_IDENTIFIER: &str = "PROXY";
63
64impl HeaderV1 {
65 pub fn new(addr_src: SocketAddr, addr_dst: SocketAddr) -> Self {
66 let protocol = if addr_dst.is_ipv6() {
67 ProtocolSupportedV1::TCP6
68 } else if addr_dst.is_ipv4() {
69 ProtocolSupportedV1::TCP4
70 } else {
71 ProtocolSupportedV1::UNKNOWN
72 };
73
74 HeaderV1 {
75 protocol,
76 addr_src,
77 addr_dst,
78 }
79 }
80
81 pub fn into_bytes(&self) -> Vec<u8> {
82 if self.protocol.eq(&ProtocolSupportedV1::UNKNOWN) {
83 format!("{} {}\r\n", PROXY_PROTO_IDENTIFIER, self.protocol,).into_bytes()
84 } else {
85 format!(
86 "{} {} {} {} {} {}\r\n",
87 PROXY_PROTO_IDENTIFIER,
88 self.protocol,
89 self.addr_src.ip(),
90 self.addr_dst.ip(),
91 self.addr_src.port(),
92 self.addr_dst.port(),
93 )
94 .into_bytes()
95 }
96 }
97}
98
99#[derive(Debug, PartialEq, Eq)]
133pub enum Command {
134 Local,
135 Proxy,
136}
137
138#[derive(Debug, PartialEq)]
139pub struct HeaderV2 {
140 pub command: Command,
141 pub family: u8, pub addr: ProxyAddr,
143}
144
145impl HeaderV2 {
146 pub fn new(command: Command, addr_src: SocketAddr, addr_dst: SocketAddr) -> Self {
147 let addr = ProxyAddr::from(addr_src, addr_dst);
148
149 HeaderV2 {
150 command,
151 family: get_family(&addr),
152 addr,
153 }
154 }
155
156 pub fn into_bytes(&self) -> Vec<u8> {
157 let mut header = Vec::with_capacity(self.len());
158
159 let signature = [
160 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
161 ];
162 header.extend_from_slice(&signature);
163
164 let command = match self.command {
165 Command::Local => 0,
166 Command::Proxy => 1,
167 };
168 let ver_and_cmd = 0x20 | command;
169 header.push(ver_and_cmd);
170
171 header.push(self.family);
172 header.extend_from_slice(&u16_to_array_of_u8(self.addr.len()));
173 self.addr.write_bytes_to(&mut header);
174 header
175 }
176
177 pub fn len(&self) -> usize {
178 12 + 1 + 1 + 2 + self.addr.len() as usize
180 }
181
182 pub fn is_empty(&self) -> bool {
183 0 == self.len()
184 }
185}
186
187pub enum ProxyAddr {
188 Ipv4Addr {
189 src_addr: SocketAddrV4,
190 dst_addr: SocketAddrV4,
191 },
192 Ipv6Addr {
193 src_addr: SocketAddrV6,
194 dst_addr: SocketAddrV6,
195 },
196 UnixAddr {
197 src_addr: [u8; 108],
198 dst_addr: [u8; 108],
199 },
200 AfUnspec,
201}
202
203impl ProxyAddr {
204 pub fn from(addr_src: SocketAddr, addr_dst: SocketAddr) -> Self {
205 match (addr_src, addr_dst) {
206 (SocketAddr::V4(addr_ipv4_src), SocketAddr::V4(addr_ipv4_dst)) => ProxyAddr::Ipv4Addr {
207 src_addr: addr_ipv4_src,
208 dst_addr: addr_ipv4_dst,
209 },
210 (SocketAddr::V6(addr_ipv6_src), SocketAddr::V6(addr_ipv6_dst)) => ProxyAddr::Ipv6Addr {
211 src_addr: addr_ipv6_src,
212 dst_addr: addr_ipv6_dst,
213 },
214 _ => ProxyAddr::AfUnspec,
215 }
216 }
217
218 fn len(&self) -> u16 {
219 match *self {
220 ProxyAddr::Ipv4Addr { .. } => 12,
221 ProxyAddr::Ipv6Addr { .. } => 36,
222 ProxyAddr::UnixAddr { .. } => 216,
223 ProxyAddr::AfUnspec => 0,
224 }
225 }
226
227 pub fn source(&self) -> Option<SocketAddr> {
228 match self {
229 ProxyAddr::Ipv4Addr { src_addr: src, .. } => Some(SocketAddr::V4(*src)),
230 ProxyAddr::Ipv6Addr { src_addr: src, .. } => Some(SocketAddr::V6(*src)),
231 _ => None,
232 }
233 }
234
235 pub fn destination(&self) -> Option<SocketAddr> {
236 match self {
237 ProxyAddr::Ipv4Addr { dst_addr: dst, .. } => Some(SocketAddr::V4(*dst)),
238 ProxyAddr::Ipv6Addr { dst_addr: dst, .. } => Some(SocketAddr::V6(*dst)),
239 _ => None,
240 }
241 }
242
243 fn write_bytes_to(&self, buf: &mut Vec<u8>) {
245 match *self {
246 ProxyAddr::Ipv4Addr { src_addr, dst_addr } => {
247 buf.extend_from_slice(&src_addr.ip().octets());
248 buf.extend_from_slice(&dst_addr.ip().octets());
249 buf.extend_from_slice(&u16_to_array_of_u8(src_addr.port()));
250 buf.extend_from_slice(&u16_to_array_of_u8(dst_addr.port()));
251 }
252 ProxyAddr::Ipv6Addr { src_addr, dst_addr } => {
253 buf.extend_from_slice(&src_addr.ip().octets());
254 buf.extend_from_slice(&dst_addr.ip().octets());
255 buf.extend_from_slice(&u16_to_array_of_u8(src_addr.port()));
256 buf.extend_from_slice(&u16_to_array_of_u8(dst_addr.port()));
257 }
258 ProxyAddr::UnixAddr { src_addr, dst_addr } => {
259 buf.extend_from_slice(&src_addr);
260 buf.extend_from_slice(&dst_addr);
261 }
262 ProxyAddr::AfUnspec => {}
263 };
264 }
265}
266
267impl fmt::Debug for ProxyAddr {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 match *self {
271 ProxyAddr::Ipv4Addr { src_addr, dst_addr } => {
272 write!(f, "{dst_addr:?} {src_addr:?}")
273 }
274 ProxyAddr::Ipv6Addr { src_addr, dst_addr } => {
275 write!(f, "{dst_addr:?} {src_addr:?}")
276 }
277 ProxyAddr::UnixAddr { src_addr, dst_addr } => {
278 write!(f, "{:?} {:?}", &dst_addr[..], &src_addr[..])
279 }
280 ProxyAddr::AfUnspec => write!(f, "AFUNSPEC"),
281 }
282 }
283}
284
285impl PartialEq for ProxyAddr {
287 fn eq(&self, other: &ProxyAddr) -> bool {
288 match *self {
289 ProxyAddr::Ipv4Addr { src_addr, dst_addr } => match other {
290 ProxyAddr::Ipv4Addr {
291 src_addr: src_other,
292 dst_addr: dst_other,
293 } => *src_other == src_addr && *dst_other == dst_addr,
294 _ => false,
295 },
296 ProxyAddr::Ipv6Addr { src_addr, dst_addr } => match other {
297 ProxyAddr::Ipv6Addr {
298 src_addr: src_other,
299 dst_addr: dst_other,
300 } => *src_other == src_addr && *dst_other == dst_addr,
301 _ => false,
302 },
303 ProxyAddr::UnixAddr { src_addr, dst_addr } => match other {
304 ProxyAddr::UnixAddr {
305 src_addr: src_other,
306 dst_addr: dst_other,
307 } => src_other[..] == src_addr[..] && dst_other[..] == dst_addr[..],
308 _ => false,
309 },
310 ProxyAddr::AfUnspec => {
311 if let ProxyAddr::AfUnspec = other {
312 return true;
313 }
314 false
315 }
316 }
317 }
318}
319
320fn get_family(addr: &ProxyAddr) -> u8 {
321 match *addr {
322 ProxyAddr::Ipv4Addr { .. } => 0x10 | 0x01, ProxyAddr::Ipv6Addr { .. } => 0x20 | 0x01, ProxyAddr::UnixAddr { .. } => 0x30 | 0x01, ProxyAddr::AfUnspec => 0x00, }
327}
328
329fn u16_to_array_of_u8(x: u16) -> [u8; 2] {
330 let b1: u8 = ((x >> 8) & 0xff) as u8;
331 let b2: u8 = (x & 0xff) as u8;
332 [b1, b2]
333}
334
335#[cfg(test)]
336mod test_v2 {
337
338 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
339
340 use super::*;
341
342 #[test]
343 fn test_u16_to_array_of_u8() {
344 let val_u16: u16 = 65534;
345 let expected = [0xff, 0xfe];
346 assert_eq!(expected, u16_to_array_of_u8(val_u16));
347 }
348
349 #[test]
350 fn test_deserialize_tcp_ipv4_proxy_protocol_header() {
351 let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
352 let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
353
354 let header = HeaderV2::new(Command::Local, src_addr, dst_addr);
355 let expected = &[
356 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
357 0x0A, 0x20, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
366
367 assert_eq!(expected, &header.into_bytes()[..]);
368 }
369
370 #[test]
371 fn test_deserialize_tcp_ipv6_proxy_protocol_header() {
372 let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
373 let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 4200);
374
375 let header = HeaderV2::new(Command::Proxy, src_addr, dst_addr);
376 let expected = [
377 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
378 0x0A, 0x21, 0x21, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x01, 0x1F, 0x90, 0x10, 0x68,
388 ];
389
390 assert_eq!(&expected[..], &header.into_bytes()[..]);
391 }
392}