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 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#[derive(Debug, PartialEq, Eq)]
24pub enum ProtocolSupportedV1 {
25 TCP4, TCP6, UNKNOWN, }
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#[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#[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, 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 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 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
260impl 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
278impl 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, ProxyAddr::Ipv6Addr { .. } => 0x20 | 0x01, ProxyAddr::UnixAddr { .. } => 0x30 | 0x01, ProxyAddr::AfUnspec => 0x00, }
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, 0x20, 0x11, 0x00, 0x0C, 0x7D, 0x19, 0x0A, 0x01, 0x0A, 0x04, 0x05, 0x08, 0x1F, 0x90, 0x10, 0x68, ];
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, 0x21, 0x21, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x01, 0x1F, 0x90, 0x10, 0x68,
380 ];
381
382 assert_eq!(&expected[..], &header.into_bytes()[..]);
383 }
384}