proxychains_masq/proxy/
socks4.rs1use anyhow::{bail, Context, Result};
2use tokio::io::{AsyncReadExt, AsyncWriteExt};
3
4use super::{BoxStream, Target};
5
6pub async fn connect(
15 mut stream: BoxStream,
16 target: &Target,
17 username: Option<&str>,
18) -> Result<BoxStream> {
19 let port = target.port();
20 let user_bytes = username.unwrap_or("").as_bytes();
21
22 let mut req: Vec<u8> = Vec::with_capacity(32);
24 req.push(4); req.push(1); req.extend_from_slice(&port.to_be_bytes());
29
30 match target {
31 Target::Ip(addr, _) => {
32 match addr {
33 std::net::IpAddr::V4(v4) => req.extend_from_slice(&v4.octets()),
34 std::net::IpAddr::V6(_) => bail!("SOCKS4 does not support IPv6 addresses"),
35 }
36 req.extend_from_slice(user_bytes);
37 req.push(0); }
39 Target::Host(hostname, _) => {
40 req.extend_from_slice(&[0, 0, 0, 1]);
42 req.extend_from_slice(user_bytes);
43 req.push(0); req.extend_from_slice(hostname.as_bytes());
45 req.push(0); }
47 }
48
49 stream
50 .write_all(&req)
51 .await
52 .context("socks4: write request")?;
53
54 let mut resp = [0u8; 8];
56 stream
57 .read_exact(&mut resp)
58 .await
59 .context("socks4: read response")?;
60
61 if resp[0] != 0 {
63 bail!("socks4: unexpected version byte in response: {}", resp[0]);
64 }
65 if resp[1] != 90 {
66 bail!("socks4: connection denied (status {})", resp[1]);
67 }
68
69 Ok(stream)
70}