sozu_lib/protocol/proxy_protocol/
parser.rs

1use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
2
3use nom::{
4    Err, IResult,
5    bytes::streaming::{tag, take},
6    error::{Error, ErrorKind, ParseError},
7    number::streaming::{be_u8, be_u16},
8};
9
10use crate::protocol::proxy_protocol::header::{Command, HeaderV2, ProxyAddr};
11
12const PROTOCOL_SIGNATURE_V2: [u8; 12] = [
13    0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
14];
15
16fn parse_command(i: &[u8]) -> IResult<&[u8], Command> {
17    let i2 = i;
18    let (i, cmd) = be_u8(i)?;
19    match cmd {
20        0x20 => Ok((i, Command::Local)),
21        0x21 => Ok((i, Command::Proxy)),
22        _ => Err(Err::Error(Error::from_error_kind(i2, ErrorKind::Switch))),
23    }
24}
25
26pub fn parse_v2_header(i: &[u8]) -> IResult<&[u8], HeaderV2> {
27    let (i, _) = tag(&PROTOCOL_SIGNATURE_V2)(i)?;
28    let (i, command) = parse_command(i)?;
29    let (i, family) = be_u8(i)?;
30    let (i, len) = be_u16(i)?;
31    let (i, data) = take(len)(i)?;
32    let (_, addr) = parse_addr_v2(family)(data)?;
33
34    Ok((
35        i,
36        (HeaderV2 {
37            command,
38            family,
39            addr,
40        }),
41    ))
42}
43
44fn parse_addr_v2(family: u8) -> impl Fn(&[u8]) -> IResult<&[u8], ProxyAddr> {
45    move |i: &[u8]| match (family >> 4) & 0x0f {
46        0x00 => Ok((i, ProxyAddr::AfUnspec)),
47        0x01 => parse_ipv4_on_v2(i),
48        0x02 => parse_ipv6_on_v2(i),
49        _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Switch))),
50    }
51}
52
53fn parse_ipv4_on_v2(i: &[u8]) -> IResult<&[u8], ProxyAddr> {
54    let (i, src_ip) = take(4u8)(i)?;
55    let (i, dest_ip) = take(4u8)(i)?;
56    let (i, src_port) = be_u16(i)?;
57    let (i, dest_port) = be_u16(i)?;
58
59    Ok((
60        i,
61        ProxyAddr::Ipv4Addr {
62            src_addr: SocketAddrV4::new(
63                Ipv4Addr::new(src_ip[0], src_ip[1], src_ip[2], src_ip[3]),
64                src_port,
65            ),
66            dst_addr: SocketAddrV4::new(
67                Ipv4Addr::new(dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]),
68                dest_port,
69            ),
70        },
71    ))
72}
73
74fn parse_ipv6_on_v2(i: &[u8]) -> IResult<&[u8], ProxyAddr> {
75    let (i, src_ip) = take(16u8)(i)?;
76    let (i, dest_ip) = take(16u8)(i)?;
77    let (i, src_port) = be_u16(i)?;
78    let (i, dest_port) = be_u16(i)?;
79
80    Ok((
81        i,
82        ProxyAddr::Ipv6Addr {
83            src_addr: SocketAddrV6::new(slice_to_ipv6(src_ip), src_port, 0, 0),
84            dst_addr: SocketAddrV6::new(slice_to_ipv6(dest_ip), dest_port, 0, 0),
85        },
86    ))
87}
88
89// assumes the slice has 16 bytes
90pub fn slice_to_ipv6(sl: &[u8]) -> Ipv6Addr {
91    let mut arr: [u8; 16] = [0; 16];
92    arr.clone_from_slice(sl);
93    Ipv6Addr::from(arr)
94}
95
96#[cfg(test)]
97mod test {
98
99    use std::net::{IpAddr, SocketAddr};
100
101    use nom::{Err, Needed};
102
103    use super::*;
104
105    #[test]
106    fn test_parse_proxy_protocol_v2_local_ipv4_addr_header() {
107        let input = &[
108            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
109            0x0A, // MAGIC header
110            0x20, // Version 2 and command LOCAL
111            0x11, // family AF_UNIX with IPv4
112            0x00, 0x0C, // address sizes = 12
113            0x7D, 0x19, 0x0A, 0x01, // source address
114            0x0A, 0x04, 0x05, 0x08, // destination address
115            0x1F, 0x90, // source port
116            0x10, 0x68, // destination port
117        ];
118
119        let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
120        let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
121        let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);
122
123        assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
124    }
125
126    #[test]
127    fn test_parse_proxy_protocol_v2_proxy_ipv4_addr_header() {
128        let input = &[
129            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
130            0x0A, // MAGIC header
131            0x21, // Version 2 and command LOCAL
132            0x11, // family AF_UNIX with IPv4
133            0x00, 0x0C, // address sizes = 12
134            0x7D, 0x19, 0x0A, 0x01, // source address
135            0x0A, 0x04, 0x05, 0x08, // destination address
136            0x1F, 0x90, // source port
137            0x10, 0x68, // destination port
138        ];
139
140        let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
141        let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
142        let expected = HeaderV2::new(Command::Proxy, src_addr, dst_addr);
143
144        assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
145    }
146
147    #[test]
148    fn it_should_parse_proxy_protocol_v2_ipv6_addr_header() {
149        let input = &[
150            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
151            0x0A, // MAGIC header
152            0x20, // Version 2 and command LOCAL
153            0x21, // family AF_UNIX with IPv6
154            0x00, 0x24, // address sizes = 36
155            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156            0x00, 0x01, // source address
157            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158            0x00, 0x02, // destination address
159            0x1F, 0x90, // source port
160            0x10, 0x68, // destination port
161        ];
162
163        let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
164        let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2)), 4200);
165        let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);
166
167        assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
168    }
169
170    #[test]
171    fn it_should_parse_proxy_protocol_v2_afunspec_header() {
172        let input = &[
173            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
174            0x0A, // MAGIC header
175            0x20, // Version 2 and command LOCAL
176            0x00, // family AF_UNSPEC and transport protocol unknown
177            0x00, 0x00, // address sizes = 0
178        ];
179
180        let expected = HeaderV2 {
181            command: Command::Local,
182            family: 0,
183            addr: ProxyAddr::AfUnspec,
184        };
185
186        assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
187    }
188
189    #[test]
190    fn it_should_not_parse_proxy_protocol_v2_with_unknown_version() {
191        let unknow_version = 0x30;
192
193        let input = &[
194            0x0D,
195            0x0A,
196            0x0D,
197            0x0A,
198            0x00,
199            0x0D,
200            0x0A,
201            0x51,
202            0x55,
203            0x49,
204            0x54,
205            0x0A,           // MAGIC header
206            unknow_version, // invalid version
207        ];
208
209        assert!(parse_v2_header(input).is_err());
210    }
211
212    #[test]
213    fn it_should_not_parse_proxy_protocol_v2_with_unknown_command() {
214        let unknow_command = 0x23;
215
216        let input = &[
217            0x0D,
218            0x0A,
219            0x0D,
220            0x0A,
221            0x00,
222            0x0D,
223            0x0A,
224            0x51,
225            0x55,
226            0x49,
227            0x54,
228            0x0A,           // MAGIC header
229            unknow_command, // Version 2 and invalid command
230        ];
231
232        assert!(parse_v2_header(input).is_err());
233    }
234
235    #[test]
236    fn it_should_not_parse_proxy_protocol_with_unknown_family() {
237        let unknow_family = 0x30;
238
239        let input = &[
240            0x0D,
241            0x0A,
242            0x0D,
243            0x0A,
244            0x00,
245            0x0D,
246            0x0A,
247            0x51,
248            0x55,
249            0x49,
250            0x54,
251            0x0A,          // MAGIC header
252            0x20,          // Version 2 and command LOCAL
253            unknow_family, // family
254            0x00,
255            0x00, // address sizes = 0
256        ];
257
258        assert!(parse_v2_header(input).is_err());
259    }
260
261    #[test]
262    fn it_should_not_parse_request_without_magic_header() {
263        let input = &[
264            0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
265            0x0D, // INCORRECT MAGIC header
266        ];
267
268        assert!(parse_v2_header(input).is_err());
269    }
270
271    #[test]
272    fn it_should_not_parse_proxy_protocol_v2_ipv4_addr_header_with_missing_data() {
273        let input = &[
274            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
275            0x0A, // MAGIC header
276            0x20, // Version 2 and command LOCAL
277            0x11, // family AF_UNIX with IPv4
278        ];
279
280        assert_eq!(Err(Err::Incomplete(Needed::new(2))), parse_v2_header(input));
281    }
282
283    #[test]
284    fn it_should_not_parse_proxy_protocol_v2_with_invalid_length() {
285        let input = &[
286            0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
287            0x0A, // MAGIC header
288            0x20, // Version 2 and command LOCAL
289            0x21, // family AF_UNIX with IPv6
290            0x00, 0x10, // address sizes = 36
291            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292            0x00, 0x01, // source address
293            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294            0x00, 0x02, // destination address
295            0x1F, 0x90, // source port
296            0x10, 0x68, // destination port
297        ];
298
299        assert_eq!(
300            Err(Err::Incomplete(Needed::new(16))),
301            parse_v2_header(input)
302        );
303    }
304}