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