1use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
2
3use nom::{
4 bytes::streaming::{tag, take},
5 error::{Error, ErrorKind, ParseError},
6 number::streaming::{be_u16, be_u8},
7 Err, IResult,
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 super::*;
100 use nom::Err;
101 use nom::Needed;
102 use std::net::{IpAddr, SocketAddr};
103
104 #[test]
105 fn test_parse_proxy_protocol_v2_local_ipv4_addr_header() {
106 let input = &[
107 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
108 0x0A, 0x20, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
117
118 let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
119 let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
120 let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);
121
122 assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
123 }
124
125 #[test]
126 fn test_parse_proxy_protocol_v2_proxy_ipv4_addr_header() {
127 let input = &[
128 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
129 0x0A, 0x21, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
138
139 let src_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(125, 25, 10, 1)), 8080);
140 let dst_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 4, 5, 8)), 4200);
141 let expected = HeaderV2::new(Command::Proxy, src_addr, dst_addr);
142
143 assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
144 }
145
146 #[test]
147 fn it_should_parse_proxy_protocol_v2_ipv6_addr_header() {
148 let input = &[
149 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
150 0x0A, 0x20, 0x21, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x02, 0x1F, 0x90, 0x10, 0x68, ];
161
162 let src_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080);
163 let dst_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2)), 4200);
164 let expected = HeaderV2::new(Command::Local, src_addr, dst_addr);
165
166 assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
167 }
168
169 #[test]
170 fn it_should_parse_proxy_protocol_v2_afunspec_header() {
171 let input = &[
172 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
173 0x0A, 0x20, 0x00, 0x00, 0x00, ];
178
179 let expected = HeaderV2 {
180 command: Command::Local,
181 family: 0,
182 addr: ProxyAddr::AfUnspec,
183 };
184
185 assert_eq!(Ok((&[][..], expected)), parse_v2_header(input));
186 }
187
188 #[test]
189 fn it_should_not_parse_proxy_protocol_v2_with_unknown_version() {
190 let unknow_version = 0x30;
191
192 let input = &[
193 0x0D,
194 0x0A,
195 0x0D,
196 0x0A,
197 0x00,
198 0x0D,
199 0x0A,
200 0x51,
201 0x55,
202 0x49,
203 0x54,
204 0x0A, unknow_version, ];
207
208 assert!(parse_v2_header(input).is_err());
209 }
210
211 #[test]
212 fn it_should_not_parse_proxy_protocol_v2_with_unknown_command() {
213 let unknow_command = 0x23;
214
215 let input = &[
216 0x0D,
217 0x0A,
218 0x0D,
219 0x0A,
220 0x00,
221 0x0D,
222 0x0A,
223 0x51,
224 0x55,
225 0x49,
226 0x54,
227 0x0A, unknow_command, ];
230
231 assert!(parse_v2_header(input).is_err());
232 }
233
234 #[test]
235 fn it_should_not_parse_proxy_protocol_with_unknown_family() {
236 let unknow_family = 0x30;
237
238 let input = &[
239 0x0D,
240 0x0A,
241 0x0D,
242 0x0A,
243 0x00,
244 0x0D,
245 0x0A,
246 0x51,
247 0x55,
248 0x49,
249 0x54,
250 0x0A, 0x20, unknow_family, 0x00,
254 0x00, ];
256
257 assert!(parse_v2_header(input).is_err());
258 }
259
260 #[test]
261 fn it_should_not_parse_request_without_magic_header() {
262 let input = &[
263 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
264 0x0D, ];
266
267 assert!(parse_v2_header(input).is_err());
268 }
269
270 #[test]
271 fn it_should_not_parse_proxy_protocol_v2_ipv4_addr_header_with_missing_data() {
272 let input = &[
273 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
274 0x0A, 0x20, 0x11, ];
278
279 assert_eq!(Err(Err::Incomplete(Needed::new(2))), parse_v2_header(input));
280 }
281
282 #[test]
283 fn it_should_not_parse_proxy_protocol_v2_with_invalid_length() {
284 let input = &[
285 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54,
286 0x0A, 0x20, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x02, 0x1F, 0x90, 0x10, 0x68, ];
297
298 assert_eq!(
299 Err(Err::Incomplete(Needed::new(16))),
300 parse_v2_header(input)
301 );
302 }
303}