1use std::net::{IpAddr, SocketAddr};
9
10const PROXY_V2_SIGNATURE: [u8; 12] = [
12 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
13];
14
15const PROXY_V2_VERSION: u8 = 0x20; const PROXY_CMD_PROXY: u8 = 0x01; const AF_UNSPEC: u8 = 0x00;
21const AF_INET: u8 = 0x10; const AF_INET6: u8 = 0x20; const STREAM: u8 = 0x01; pub fn build_proxy_v2_header(client_addr: &SocketAddr, server_addr: &SocketAddr) -> Vec<u8> {
36 let mut header = Vec::with_capacity(52); header.extend_from_slice(&PROXY_V2_SIGNATURE);
40
41 let (af_proto, addr_len, addr_data) = match (client_addr.ip(), server_addr.ip()) {
43 (IpAddr::V4(src_ip), IpAddr::V4(dst_ip)) => {
44 let af_proto = AF_INET | STREAM;
46 let mut data = Vec::with_capacity(12);
47 data.extend_from_slice(&src_ip.octets()); data.extend_from_slice(&dst_ip.octets()); data.extend_from_slice(&client_addr.port().to_be_bytes()); data.extend_from_slice(&server_addr.port().to_be_bytes()); (af_proto, 12u16, data)
52 }
53 (IpAddr::V6(src_ip), IpAddr::V6(dst_ip)) => {
54 let af_proto = AF_INET6 | STREAM;
56 let mut data = Vec::with_capacity(36);
57 data.extend_from_slice(&src_ip.octets()); data.extend_from_slice(&dst_ip.octets()); data.extend_from_slice(&client_addr.port().to_be_bytes()); data.extend_from_slice(&server_addr.port().to_be_bytes()); (af_proto, 36u16, data)
62 }
63 (IpAddr::V4(src_ip), IpAddr::V6(_)) => {
64 let src_v6 = src_ip.to_ipv6_mapped();
66 let dst_v6 = match server_addr.ip() {
67 IpAddr::V6(ip) => ip,
68 _ => unreachable!(),
69 };
70 let af_proto = AF_INET6 | STREAM;
71 let mut data = Vec::with_capacity(36);
72 data.extend_from_slice(&src_v6.octets());
73 data.extend_from_slice(&dst_v6.octets());
74 data.extend_from_slice(&client_addr.port().to_be_bytes());
75 data.extend_from_slice(&server_addr.port().to_be_bytes());
76 (af_proto, 36u16, data)
77 }
78 (IpAddr::V6(_), IpAddr::V4(dst_ip)) => {
79 let src_v6 = match client_addr.ip() {
81 IpAddr::V6(ip) => ip,
82 _ => unreachable!(),
83 };
84 let dst_v6 = dst_ip.to_ipv6_mapped();
85 let af_proto = AF_INET6 | STREAM;
86 let mut data = Vec::with_capacity(36);
87 data.extend_from_slice(&src_v6.octets());
88 data.extend_from_slice(&dst_v6.octets());
89 data.extend_from_slice(&client_addr.port().to_be_bytes());
90 data.extend_from_slice(&server_addr.port().to_be_bytes());
91 (af_proto, 36u16, data)
92 }
93 };
94
95 header.push(PROXY_V2_VERSION | PROXY_CMD_PROXY);
97
98 header.push(af_proto);
100
101 header.extend_from_slice(&addr_len.to_be_bytes());
103
104 header.extend_from_slice(&addr_data);
106
107 header
108}
109
110pub fn build_proxy_v2_local_header() -> Vec<u8> {
115 let mut header = Vec::with_capacity(16);
116
117 header.extend_from_slice(&PROXY_V2_SIGNATURE);
119
120 header.push(PROXY_V2_VERSION); header.push(AF_UNSPEC);
125
126 header.extend_from_slice(&0u16.to_be_bytes());
128
129 header
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
136
137 #[test]
138 fn test_proxy_v2_header_ipv4() {
139 let client = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 100), 54321));
140 let server = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 25565));
141
142 let header = build_proxy_v2_header(&client, &server);
143
144 assert_eq!(&header[0..12], &PROXY_V2_SIGNATURE);
146
147 assert_eq!(header[12], 0x21); assert_eq!(header[13], 0x11); assert_eq!(&header[14..16], &12u16.to_be_bytes());
155
156 assert_eq!(header.len(), 28);
158
159 assert_eq!(&header[16..20], &[192, 168, 1, 100]);
161
162 assert_eq!(&header[20..24], &[10, 0, 0, 1]);
164
165 assert_eq!(&header[24..26], &54321u16.to_be_bytes());
167
168 assert_eq!(&header[26..28], &25565u16.to_be_bytes());
170 }
171
172 #[test]
173 fn test_proxy_v2_header_ipv6() {
174 let client = SocketAddr::V6(SocketAddrV6::new(
175 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
176 54321,
177 0,
178 0,
179 ));
180 let server = SocketAddr::V6(SocketAddrV6::new(
181 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2),
182 25565,
183 0,
184 0,
185 ));
186
187 let header = build_proxy_v2_header(&client, &server);
188
189 assert_eq!(&header[0..12], &PROXY_V2_SIGNATURE);
191
192 assert_eq!(header[12], 0x21); assert_eq!(header[13], 0x21); assert_eq!(&header[14..16], &36u16.to_be_bytes());
200
201 assert_eq!(header.len(), 52);
203 }
204
205 #[test]
206 fn test_proxy_v2_local_header() {
207 let header = build_proxy_v2_local_header();
208
209 assert_eq!(&header[0..12], &PROXY_V2_SIGNATURE);
211
212 assert_eq!(header[12], 0x20); assert_eq!(header[13], 0x00); assert_eq!(&header[14..16], &0u16.to_be_bytes());
220
221 assert_eq!(header.len(), 16);
223 }
224}