socks5.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{
  19. fmt::Debug,
  20. io,
  21. net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
  22. };
  23. use futures::{AsyncReadExt, AsyncWriteExt};
  24. use smol::net::TcpStream;
  25. use tracing::debug;
  26. use url::Url;
  27. /// SOCKS5 dialer
  28. #[derive(Clone, Debug)]
  29. pub struct Socks5Dialer {
  30. client: Socks5Client,
  31. endpoint: AddrKind,
  32. }
  33. impl Socks5Dialer {
  34. /// Instantiate a new [`Socks5Dialer`] with given URI
  35. pub(crate) async fn new(uri: &Url) -> io::Result<Self> {
  36. // URIs in the form of: socks5://user:pass@proxy:port/destination:port
  37. /*
  38. let auth_user = uri.username();
  39. let auth_pass = uri.password();
  40. */
  41. // Parse destination
  42. let mut dest = uri.path().strip_prefix("/").unwrap().split(':');
  43. let Some(dest_host) = dest.next() else { return Err(io::ErrorKind::InvalidInput.into()) };
  44. let Some(dest_port) = dest.next() else { return Err(io::ErrorKind::InvalidInput.into()) };
  45. let dest_port: u16 = match dest_port.parse() {
  46. Ok(v) => v,
  47. Err(_) => return Err(io::ErrorKind::InvalidData.into()),
  48. };
  49. let client = Socks5Client::new(uri.host_str().unwrap(), uri.port().unwrap());
  50. let endpoint: AddrKind = (dest_host, dest_port).into();
  51. Ok(Self { client, endpoint })
  52. }
  53. /// Internal dial function
  54. pub(crate) async fn do_dial(&self) -> io::Result<TcpStream> {
  55. debug!(
  56. target: "net::socks5::do_dial",
  57. "Dialing {:?} with SOCKS5...", self.endpoint,
  58. );
  59. self.client.connect(self.endpoint.clone()).await
  60. }
  61. }
  62. /// SOCKS5 proxy client
  63. #[derive(Clone, Debug)]
  64. pub struct Socks5Client {
  65. /// SOCKS5 server host
  66. host: String,
  67. /// SOCKS5 server port
  68. port: u16,
  69. }
  70. impl Socks5Client {
  71. /// Instantiate a new SOCKS5 client from given host and port
  72. pub fn new(host: &str, port: u16) -> Self {
  73. Self { host: String::from(host), port }
  74. }
  75. /// Connect an instantiated SOCKS5 client to the given destination
  76. pub async fn connect(&self, addr: impl Into<AddrKind> + Debug) -> io::Result<TcpStream> {
  77. let addr: AddrKind = addr.into();
  78. // Connect to the SOCKS proxy
  79. let mut stream = TcpStream::connect(&format!("{}:{}", self.host, self.port)).await?;
  80. // Send version identifier/method selection message
  81. // VER=5, NMETHODS=1, METHOD=NO_AUTH
  82. stream.write_all(&[0x05, 0x01, 0x00]).await?;
  83. stream.flush().await?;
  84. // Read server method selection message
  85. let mut buf = [0u8; 2];
  86. stream.read_exact(&mut buf).await?;
  87. // Currently we will only support METHOD=NO_AUTH (0x00)
  88. if buf[0] != 0x05 && buf[0] != 0x00 {
  89. return Err(io::ErrorKind::ConnectionRefused.into())
  90. }
  91. // Build CONNECT request
  92. // VER=5, CMD=CONNECT, RSV
  93. let mut reqbuf = vec![0x05, 0x01, 0x00];
  94. match addr {
  95. AddrKind::Ip(socketaddr) => {
  96. if socketaddr.is_ipv4() {
  97. // ATYP=0x01
  98. reqbuf.push(0x01);
  99. } else {
  100. // ATYP=0x04
  101. reqbuf.push(0x04);
  102. }
  103. // DST.ADDR
  104. match socketaddr.ip() {
  105. IpAddr::V4(ip) => reqbuf.extend_from_slice(&ip.octets()),
  106. IpAddr::V6(ip) => reqbuf.extend_from_slice(&ip.octets()),
  107. }
  108. // DST.PORT
  109. reqbuf.extend_from_slice(&socketaddr.port().to_be_bytes());
  110. }
  111. AddrKind::Domain(ref host, port) => {
  112. // ATYP=0x03
  113. reqbuf.push(0x03);
  114. // DST.ADDR
  115. reqbuf.push(host.len() as u8);
  116. reqbuf.extend_from_slice(host.as_bytes());
  117. // DST.PORT
  118. reqbuf.extend_from_slice(&port.to_be_bytes());
  119. }
  120. };
  121. // Send it
  122. stream.write_all(&reqbuf).await?;
  123. stream.flush().await?;
  124. debug!(
  125. target: "net::transport::socks5::connect",
  126. "Flushed CONNECT({addr:?}) request"
  127. );
  128. // Handle the SOCKS server reply
  129. let mut buf = [0u8];
  130. stream.read_exact(&mut buf).await?;
  131. debug!(
  132. target: "net::transport::socks5::connect",
  133. "REPLY - Version: {:#02x}", buf[0],
  134. );
  135. if buf[0] != 0x05 {
  136. return Err(io::ErrorKind::ConnectionRefused.into())
  137. }
  138. buf[0] = 0x00;
  139. stream.read_exact(&mut buf).await?;
  140. debug!(
  141. target: "net::transport::socks5::connect",
  142. "REPLY - Reply: {:#02x}", buf[0],
  143. );
  144. match buf[0] {
  145. 0x00 => {}
  146. 0x01 => return Err(io::ErrorKind::ConnectionAborted.into()),
  147. 0x02 => return Err(io::ErrorKind::PermissionDenied.into()),
  148. 0x03 => return Err(io::ErrorKind::NetworkUnreachable.into()),
  149. 0x04 => return Err(io::ErrorKind::HostUnreachable.into()),
  150. 0x05 => return Err(io::ErrorKind::ConnectionRefused.into()),
  151. 0x06 => return Err(io::ErrorKind::TimedOut.into()),
  152. 0x07 => return Err(io::ErrorKind::Unsupported.into()),
  153. 0x08 => return Err(io::ErrorKind::Unsupported.into()),
  154. _ => return Err(io::ErrorKind::ConnectionAborted.into()),
  155. }
  156. // Read RSV
  157. stream.read_exact(&mut buf).await?;
  158. // Read ATYP
  159. buf[0] = 0x00;
  160. stream.read_exact(&mut buf).await?;
  161. debug!(
  162. target: "net::transport::socks5::connect",
  163. "REPLY - ATYP: {:#02x}", buf[0],
  164. );
  165. // Read BND.ADDR accordingly
  166. match buf[0] {
  167. // IPv4
  168. 0x01 => {
  169. let mut buf = [0u8; 4];
  170. stream.read_exact(&mut buf).await?;
  171. debug!(
  172. target: "net::transport::socks5::connect",
  173. "REPLY - BND.ADDR: {}", Ipv4Addr::from(buf),
  174. );
  175. }
  176. // IPv6
  177. 0x04 => {
  178. let mut buf = [0u8; 16];
  179. stream.read_exact(&mut buf).await?;
  180. debug!(
  181. target: "net::transport::socks5::connect",
  182. "REPLY - BND.ADDR: {}", Ipv6Addr::from(buf),
  183. );
  184. }
  185. // Domain
  186. 0x03 => {
  187. let mut len = [0u8];
  188. stream.read_exact(&mut len).await?;
  189. let mut buf = vec![0u8; len[0] as usize];
  190. stream.read_exact(&mut buf).await?;
  191. debug!(
  192. target: "net::transport::socks5::connect",
  193. "REPLY - BND.ADDR: {}", String::from_utf8_lossy(&buf),
  194. );
  195. }
  196. _ => return Err(io::ErrorKind::ConnectionAborted.into()),
  197. };
  198. // Read BND.PORT
  199. let mut buf = [0u8; 2];
  200. stream.read_exact(&mut buf).await?;
  201. debug!(
  202. target: "net::transport::socks5::connect",
  203. "REPLY - BND.PORT: {}", u16::from_be_bytes(buf),
  204. );
  205. Ok(stream)
  206. }
  207. }
  208. #[derive(Clone, Debug)]
  209. pub enum AddrKind {
  210. Ip(SocketAddr),
  211. Domain(String, u16),
  212. }
  213. impl From<(IpAddr, u16)> for AddrKind {
  214. fn from(value: (IpAddr, u16)) -> Self {
  215. Self::Ip(value.into())
  216. }
  217. }
  218. impl From<(Ipv4Addr, u16)> for AddrKind {
  219. fn from(value: (Ipv4Addr, u16)) -> Self {
  220. Self::Ip(value.into())
  221. }
  222. }
  223. impl From<(Ipv6Addr, u16)> for AddrKind {
  224. fn from(value: (Ipv6Addr, u16)) -> Self {
  225. Self::Ip(value.into())
  226. }
  227. }
  228. impl From<(String, u16)> for AddrKind {
  229. fn from((domain, port): (String, u16)) -> Self {
  230. Self::Domain(domain, port)
  231. }
  232. }
  233. impl From<(&'_ str, u16)> for AddrKind {
  234. fn from((domain, port): (&'_ str, u16)) -> Self {
  235. Self::Domain(domain.to_owned(), port)
  236. }
  237. }
  238. impl From<SocketAddr> for AddrKind {
  239. fn from(value: SocketAddr) -> Self {
  240. Self::Ip(value)
  241. }
  242. }
  243. impl From<SocketAddrV4> for AddrKind {
  244. fn from(value: SocketAddrV4) -> Self {
  245. Self::Ip(value.into())
  246. }
  247. }
  248. impl From<SocketAddrV6> for AddrKind {
  249. fn from(value: SocketAddrV6) -> Self {
  250. Self::Ip(value.into())
  251. }
  252. }