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
89pub 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, 0x20, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
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, 0x21, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
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, 0x20, 0x21, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x02, 0x1F, 0x90, 0x10, 0x68, ];
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, 0x20, 0x00, 0x00, 0x00, ];
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, unknow_version, ];
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, unknow_command, ];
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, 0x20, unknow_family, 0x00,
255 0x00, ];
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, ];
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, 0x20, 0x11, ];
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, 0x20, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x02, 0x1F, 0x90, 0x10, 0x68, ];
298
299 assert_eq!(
300 Err(Err::Incomplete(Needed::new(16))),
301 parse_v2_header(input)
302 );
303 }
304}