1use actix_codec::Decoder;
11use actix_codec::Encoder;
12use actix_web::web::BytesMut;
13use byteorder::BigEndian;
14use byteorder::ByteOrder;
15use log::trace;
16use std::io::Error;
17use std::io::ErrorKind;
18
19use crate::codec::cli::CliCodec;
20use crate::codec::socks::SocksCodec;
21mod cli;
22pub mod forward;
23pub mod socks;
24trait VisitorDecoder {
25 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<VisitorRequest>, Error>;
26}
27pub struct VisitorCodec {
28 proto: Proto,
29 handler: Option<Box<dyn VisitorDecoder>>,
30}
31impl Default for VisitorCodec {
32 fn default() -> Self {
33 VisitorCodec {
34 proto: Proto::Undefined,
35 handler: None,
36 }
37 }
38}
39#[allow(dead_code)]
40#[derive(Debug, PartialEq, Clone)]
41pub(crate) enum State {
42 Undefined,
43 Greeting,
44 Auth,
45 Forward,
46}
47#[derive(Debug, PartialEq, Clone)]
48pub enum Proto {
49 Undefined,
50 Socks5,
51 Cli,
52}
53#[derive(Debug, PartialEq)]
54pub enum Cmd {
55 Connection,
56 Binding,
57 AssociateUdp,
58}
59#[derive(Debug, PartialEq, Clone)]
60pub enum T {
61 IPv4,
62 Domain,
63}
64#[derive(Debug, PartialEq, Clone)]
65pub struct DstAddress {
66 pub(crate) t: T,
67 pub(crate) addr: String,
68 pub(crate) port: u16,
69}
70impl DstAddress {
71 pub fn new(t: T, addr: &str, port: u16) -> Self {
72 DstAddress {
73 t,
74 addr: addr.into(),
75 port,
76 }
77 }
78}
79impl DstAddress {
80 fn port(&self) -> Vec<u8> {
81 let mut rs = [0; 2];
82 BigEndian::write_u16(&mut rs, self.port);
83 rs.to_vec()
84 }
85 fn address(&self) -> Vec<u8> {
86 let mut rs = vec![];
87 match self.t {
88 T::IPv4 => {
89 rs.push(0x01);
90 for row in self.addr.split('.') {
91 rs.push(row.parse::<u8>().unwrap());
92 }
93 }
94 T::Domain => {
95 rs.push(0x03);
96 rs.push(self.addr.len() as u8);
97 rs.extend(self.addr.as_bytes());
98 }
99 }
100 rs
101 }
102}
103impl From<DstAddress> for Vec<u8> {
104 fn from(addr: DstAddress) -> Vec<u8> {
105 let mut rs = vec![];
106 rs.extend(addr.address());
107 rs.extend(addr.port());
108 rs
109 }
110}
111#[derive(Debug, PartialEq)]
112pub enum VisitorRequest {
113 Greeting { proto: Proto, auth: Vec<u8> },
114 Auth { id: String, pwd: String },
115 Connection { cmd: Cmd, address: DstAddress },
116 Forward(Vec<u8>),
117 Cli(inn_common::cli::Cli),
118}
119#[derive(Debug, PartialEq)]
120pub enum AuthChoice {
121 NoAuth,
122 UserNamePwd,
123 NoAcceptable,
124}
125impl From<AuthChoice> for u8 {
126 fn from(choice: AuthChoice) -> u8 {
127 match choice {
128 AuthChoice::NoAcceptable => 0xFF,
129 AuthChoice::UserNamePwd => 0x02,
130 AuthChoice::NoAuth => 0x00,
131 }
132 }
133}
134impl From<u8> for AuthChoice {
135 fn from(v: u8) -> Self {
136 match v {
137 0x02 => AuthChoice::UserNamePwd,
138 0x00 => AuthChoice::NoAuth,
139 _ => AuthChoice::NoAcceptable,
140 }
141 }
142}
143#[derive(Debug, PartialEq, Clone)]
144pub enum BindStatus {
145 Granted,
146 Failure,
147 NotAllowedRuleSet,
148 NetWorkUnReachable,
149 HostUnReachable,
150 ConnectionRefuse,
151 TTLExpired,
152 CommandNotSupported,
153 AddressTypeNotSupported,
154}
155impl From<BindStatus> for u8 {
156 fn from(status: BindStatus) -> u8 {
157 match status {
158 BindStatus::Granted => 0x00,
159 BindStatus::Failure => 0x01,
160 BindStatus::NotAllowedRuleSet => 0x02,
161 BindStatus::NetWorkUnReachable => 0x03,
162 BindStatus::HostUnReachable => 0x04,
163 BindStatus::ConnectionRefuse => 0x05,
164 BindStatus::TTLExpired => 0x06,
165 BindStatus::CommandNotSupported => 0x07,
166 BindStatus::AddressTypeNotSupported => 0x08,
167 }
168 }
169}
170#[derive(Debug, PartialEq)]
171pub enum VisitorResponse {
172 Choice(AuthChoice),
173 AuthRespSuccess,
174 AuthRespError,
175 BindResp {
176 status: BindStatus,
177 address: Option<DstAddress>,
178 },
179 Forward(Vec<u8>),
180 Cli(inn_common::cli::Cli),
181}
182impl From<VisitorResponse> for Vec<u8> {
183 #[allow(clippy::vec_init_then_push)]
184 fn from(resp: VisitorResponse) -> Vec<u8> {
185 match resp {
186 VisitorResponse::Choice(choice) => {
187 let mut rs = vec![];
188 rs.push(0x5);
189 rs.push(choice.into());
190 rs
191 }
192 VisitorResponse::AuthRespSuccess => {
193 vec![0x5, 0x00]
194 }
195 VisitorResponse::AuthRespError => {
196 vec![0x5, 0x01]
197 }
198 VisitorResponse::BindResp { status, address } => {
199 let mut rs = vec![];
200 rs.push(0x05);
201 rs.push(status.clone().into());
202 if status == BindStatus::Granted {
203 if let Some(address) = address {
204 rs.push(0x00);
205 let addr: Vec<u8> = address.into();
206 rs.extend(addr);
207 }
208 }
209 rs
210 }
211 VisitorResponse::Forward(data) => data,
212 VisitorResponse::Cli(cli) => cli.into(),
213 }
214 }
215}
216impl Decoder for VisitorCodec {
217 type Item = VisitorRequest;
218 type Error = Error;
219 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
220 trace!("Client data:{:?}", src.to_vec());
221 if src.is_empty() {
222 return Ok(None);
223 }
224 if self.proto == Proto::Undefined {
226 if src.as_ref()[0] == 0x05 {
227 self.proto = Proto::Socks5;
228 self.handler = Some(Box::new(SocksCodec::default()))
229 } else if src.as_ref()[0] == b'*'
230 || src.as_ref()[0] == b'+'
231 || src.as_ref()[0] == b'-'
232 || src.as_ref()[0] == b':'
233 || src.as_ref()[0] == b'$'
234 {
235 self.proto = Proto::Cli;
236 self.handler = Some(Box::new(CliCodec::default()))
237 }
238 }
239 match &mut self.handler {
240 Some(handler) => handler.decode(src),
241 _ => Err(Error::new(ErrorKind::Other, "Invalid protocol")),
242 }
243 }
244}
245impl Encoder<VisitorResponse> for VisitorCodec {
246 type Error = Error;
247 fn encode(&mut self, item: VisitorResponse, dst: &mut BytesMut) -> Result<(), Self::Error> {
248 trace!("proto={:?}, VisitorResponse = {:?}", self.proto, item);
249 let buf: Vec<u8> = item.into();
250 dst.extend_from_slice(buf.as_slice());
251 Ok(())
252 }
253}
254
255#[cfg(test)]
256mod test {
257 use super::*;
258 #[test]
259 fn visitor_response_encode() {
260 check_visitor_response(VisitorResponse::AuthRespError, vec![0x05, 0x01]);
261 check_visitor_response(VisitorResponse::AuthRespSuccess, vec![0x05, 0x00]);
262 check_visitor_response(
263 VisitorResponse::Choice(AuthChoice::NoAuth),
264 vec![0x05, 0x00],
265 );
266 check_visitor_response(
267 VisitorResponse::Choice(AuthChoice::UserNamePwd),
268 vec![0x05, 0x02],
269 );
270 check_visitor_response(
271 VisitorResponse::Choice(AuthChoice::NoAcceptable),
272 vec![0x05, 0xFF],
273 );
274 check_visitor_response(
275 VisitorResponse::BindResp {
276 status: BindStatus::Failure,
277 address: None,
278 },
279 vec![0x05, 0x01],
280 );
281 check_visitor_response(
282 VisitorResponse::BindResp {
283 status: BindStatus::Granted,
284 address: Some(DstAddress::new(T::IPv4, "127.0.0.1", 80)),
285 },
286 vec![0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0, 80],
287 );
288 check_visitor_response(
289 VisitorResponse::BindResp {
290 status: BindStatus::Granted,
291 address: Some(DstAddress::new(T::Domain, "abc", 80)),
292 },
293 vec![0x05, 0x00, 0x00, 0x03, 0x03, 97, 98, 99, 0, 80],
294 );
295 check_visitor_response(
296 VisitorResponse::Forward(vec![1, 2, 3, 4, 5]),
297 vec![1, 2, 3, 4, 5],
298 );
299 }
300 fn check_visitor_response(resp: VisitorResponse, expected: Vec<u8>) {
301 let rs: Vec<u8> = resp.into();
302 assert_eq!(rs, expected);
303 }
304 #[test]
305 fn socks5_decode() {
306 check_none(vec![5]);
307 check_none(vec![5, 1]);
308 check_none(vec![5, 2, 0]);
309 check_greeting(
310 vec![5, 1, 1],
311 VisitorRequest::Greeting {
312 proto: Proto::Socks5,
313 auth: vec![1],
314 },
315 vec![],
316 );
317 check_greeting(
318 vec![5, 2, 0, 1],
319 VisitorRequest::Greeting {
320 proto: Proto::Socks5,
321 auth: vec![0, 1],
322 },
323 vec![],
324 );
325 check_greeting(
326 vec![5, 2, 0, 1, 4],
327 VisitorRequest::Greeting {
328 proto: Proto::Socks5,
329 auth: vec![0, 1],
330 },
331 vec![4],
332 );
333 check_auth_none(vec![5, 3, 97, 98, 99, 1], vec![5, 3, 97, 98, 99, 1]);
334 check_auth_none(vec![5, 3, 97, 98, 99], vec![5, 3, 97, 98, 99]);
335 check_auth_none(vec![5, 3, 97, 98], vec![5, 3, 97, 98]);
336 check_auth_none(vec![5, 3], vec![5, 3]);
337 check_auth_none(vec![5], vec![5]);
338 check_auth_none(vec![], vec![]);
339 check_auth(
341 vec![5, 3, 97, 98, 99, 1, 100],
342 VisitorRequest::Auth {
343 id: "abc".into(),
344 pwd: "d".into(),
345 },
346 vec![],
347 );
348 check_auth(
350 vec![5, 3, 97, 98, 99, 1, 100, 200],
351 VisitorRequest::Auth {
352 id: "abc".into(),
353 pwd: "d".into(),
354 },
355 vec![200],
356 );
357 check_connection_none(
358 vec![5, 1, 0, 1, 192, 168, 1, 1, 0],
359 vec![5, 1, 0, 1, 192, 168, 1, 1, 0],
360 );
361 check_connection_none(
362 vec![5, 1, 0, 1, 192, 168, 1, 1],
363 vec![5, 1, 0, 1, 192, 168, 1, 1],
364 );
365 check_connection_none(vec![5, 1, 0, 1, 192, 168], vec![5, 1, 0, 1, 192, 168]);
366 check_connection_none(vec![5, 1, 0, 1], vec![5, 1, 0, 1]);
367 check_connection_none(vec![5, 1, 0], vec![5, 1, 0]);
368
369 check_connection_none(
370 vec![5, 1, 0, 3, 3, 97, 97, 98, 0],
371 vec![5, 1, 0, 3, 3, 97, 97, 98, 0],
372 );
373 check_connection_none(vec![5, 1, 0, 3, 3, 97, 97], vec![5, 1, 0, 3, 3, 97, 97]);
374 check_connection_none(vec![5, 1, 0, 3, 3], vec![5, 1, 0, 3, 3]);
375 check_connection_none(vec![5, 1, 0, 3], vec![5, 1, 0, 3]);
376 check_connection_none(vec![5, 1, 0], vec![5, 1, 0]);
377 check_connection_none(vec![], vec![]);
378 check_connection(
381 vec![5, 1, 0, 1, 192, 168, 1, 1, 0, 80],
382 VisitorRequest::Connection {
383 cmd: Cmd::Connection,
384 address: DstAddress::new(T::IPv4, "192.168.1.1", 80),
385 },
386 vec![],
387 );
388 check_connection(
390 vec![5, 1, 0, 3, 3, 97, 97, 98, 0, 80],
391 VisitorRequest::Connection {
392 cmd: Cmd::Connection,
393 address: DstAddress::new(T::Domain, "aab", 80),
394 },
395 vec![],
396 );
397 }
398 fn check_none(input: Vec<u8>) {
399 let mut codec = SocksCodec::default();
400 let mut bytes = BytesMut::from(input.as_slice());
401 let rs = codec.decode(&mut bytes).unwrap();
402 assert_eq!(rs, None);
403 assert_eq!(bytes.to_vec(), input);
404 }
405 fn check_greeting(input: Vec<u8>, greeting: VisitorRequest, remain: Vec<u8>) {
406 let mut codec = SocksCodec::default();
407 let mut bytes = BytesMut::from(input.as_slice());
408 let rs = codec.decode(&mut bytes).unwrap();
409 assert_eq!(codec.state, State::Greeting);
410 assert_eq!(rs, Some(greeting));
411 assert_eq!(bytes.to_vec(), remain);
412 }
413 fn check_auth(input: Vec<u8>, auth: VisitorRequest, remain: Vec<u8>) {
414 let mut codec = SocksCodec::default();
415 let mut bytes = BytesMut::from(input.as_slice());
416 codec.state = State::Greeting;
417 let rs = codec.decode(&mut bytes).unwrap();
418 assert_eq!(codec.state, State::Auth);
419 assert_eq!(rs, Some(auth));
420 assert_eq!(bytes.to_vec(), remain);
421 }
422 fn check_auth_none(input: Vec<u8>, remain: Vec<u8>) {
423 let mut codec = SocksCodec::default();
424 let mut bytes = BytesMut::from(input.as_slice());
425 codec.state = State::Greeting;
426 let rs = codec.decode(&mut bytes).unwrap();
427 assert_eq!(codec.state, State::Greeting);
428 assert_eq!(rs, None);
429 assert_eq!(bytes.to_vec(), remain);
430 }
431 fn check_connection(input: Vec<u8>, connection: VisitorRequest, remain: Vec<u8>) {
432 let mut codec = SocksCodec::default();
433 let mut bytes = BytesMut::from(input.as_slice());
434 codec.state = State::Auth;
435 let rs = codec.decode(&mut bytes).unwrap();
436 assert_eq!(codec.state, State::Forward);
437 assert_eq!(rs, Some(connection));
438 assert_eq!(bytes.to_vec(), remain);
439 }
440 fn check_connection_none(input: Vec<u8>, remain: Vec<u8>) {
441 let mut codec = SocksCodec::default();
442 let mut bytes = BytesMut::from(input.as_slice());
443 codec.state = State::Auth;
444 let rs = codec.decode(&mut bytes).unwrap();
445 assert_eq!(codec.state, State::Auth);
446 assert_eq!(rs, None);
447 assert_eq!(bytes.to_vec(), remain);
448 }
449}