sozu_lib/protocol/proxy_protocol/
header.rs

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    // Use this method to writte the header in the backend socket
14    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/// Indicate the proxied INET protocol and family
23#[derive(Debug, PartialEq, Eq)]
24pub enum ProtocolSupportedV1 {
25    TCP4,    // TCP over IPv4
26    TCP6,    // TCP over IPv6
27    UNKNOWN, // unsupported,or unknown protocols
28}
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/// WARNING: proxy protocol v1 is never used in Sōzu, only v2.
41/// The tests have been commented out, the whole code may be meant for deletion.
42///
43/// Proxy Protocol header for version 1 (text version)
44/// Example:
45/// - TCP/IPv4: `PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n`
46/// - TCP/IPv6: `PROXY TCP6 ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n`
47/// - Unknown: `PROXY UNKNOWN\r\n`
48#[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/*
93#[cfg(test)]
94mod test {
95
96    use super::*;
97    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
98
99    #[test]
100    fn it_should_return_a_correct_header_with_ipv4() {
101        let header = HeaderV1::new(
102            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80),
103            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(172, 17, 40, 59)), 80),
104        );
105
106        let header_to_cmp = "PROXY TCP4 127.0.0.1 172.17.40.59 80 80\r\n".as_bytes();
107
108        assert_eq!(header_to_cmp, &header.into_bytes()[..]);
109    }
110
111    #[test]
112    fn it_should_return_a_correct_header_with_ipv6() {
113        let header = HeaderV1::new(
114            SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0xffff)), 80),
115            SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x9c, 0x76)), 80),
116        );
117
118        let header_to_cmp = "PROXY TCP6 ::ffff ::9c:76 80 80\r\n".as_bytes();
119
120        assert_eq!(header_to_cmp, &header.into_bytes()[..]);
121    }
122}
123*/
124
125#[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, // protocol family and address
135    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        // signature + ver_and_cmd + family + len + addr
172        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    // TODO: rename to a less ambiguous name, like "write bytes to buffer"
237    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
260// Implemented because we don't have the Debug for [u8; 108] (UnixAddr case)
261impl 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
278// Implemented because we don't have the PartialEq for [u8; 108] (UnixAddr case)
279impl 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, // AF_INET  = 1 + STREAM = 1
316        ProxyAddr::Ipv6Addr { .. } => 0x20 | 0x01, // AF_INET6 = 2 + STREAM = 1
317        ProxyAddr::UnixAddr { .. } => 0x30 | 0x01, // AF_UNIX  = 3 + STREAM = 1
318        ProxyAddr::AfUnspec => 0x00,               // AF_UNSPEC + UNSPEC
319    }
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 super::*;
332    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
333
334    #[test]
335    fn test_u16_to_array_of_u8() {
336        let val_u16: u16 = 65534;
337        let expected = [0xff, 0xfe];
338        assert_eq!(expected, u16_to_array_of_u8(val_u16));
339    }
340
341    #[test]
342    fn test_deserialize_tcp_ipv4_proxy_protocol_header() {
343        let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
344        let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
345
346        let header = HeaderV2::new(Command::Local, src_addr, dst_addr);
347        let expected = &[
348            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
349            0x0A, // MAGIC header
350            0x20, // Version 2 and command LOCAL
351            0x11, // family AF_UNIX with IPv4
352            0x00, 0x0C, // address sizes = 12
353            0x7D, 0x19, 0x0A, 0x01, // source address
354            0x0A, 0x04, 0x05, 0x08, // destination address
355            0x1F, 0x90, // source port
356            0x10, 0x68, // destination port
357        ];
358
359        assert_eq!(expected, &header.into_bytes()[..]);
360    }
361
362    #[test]
363    fn test_deserialize_tcp_ipv6_proxy_protocol_header() {
364        let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
365        let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 4200);
366
367        let header = HeaderV2::new(Command::Proxy, src_addr, dst_addr);
368        let expected = [
369            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
370            0x0A, // MAGIC header
371            0x21, // Version 2 and command PROXY
372            0x21, // family AF_UNIX with IPv6
373            0x00, 0x24, // address sizes = 36
374            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375            0x00, 0x01, // source address
376            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377            0x00, 0x01, // destination address
378            0x1F, 0x90, // source port
379            0x10, 0x68,
380        ];
381
382        assert_eq!(&expected[..], &header.into_bytes()[..]);
383    }
384}