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