Skip to main content

socks5_impl/
address.rs

1#[cfg(feature = "tokio")]
2use crate::stream::AsyncStreamOperation;
3use crate::stream::StreamOperation;
4use bytes::BufMut;
5use std::{
6    io::Cursor,
7    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs},
8};
9#[cfg(feature = "tokio")]
10use tokio::io::{AsyncRead, AsyncReadExt};
11
12#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Default)]
13#[repr(u8)]
14pub enum AddressType {
15    #[default]
16    IPv4 = 0x01,
17    Domain = 0x03,
18    IPv6 = 0x04,
19}
20
21impl TryFrom<u8> for AddressType {
22    type Error = std::io::Error;
23    fn try_from(code: u8) -> core::result::Result<Self, Self::Error> {
24        let err = format!("Unsupported address type code {code:#x}");
25        match code {
26            0x01 => Ok(AddressType::IPv4),
27            0x03 => Ok(AddressType::Domain),
28            0x04 => Ok(AddressType::IPv6),
29            _ => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, err)),
30        }
31    }
32}
33
34impl From<AddressType> for u8 {
35    fn from(addr_type: AddressType) -> Self {
36        match addr_type {
37            AddressType::IPv4 => 0x01,
38            AddressType::Domain => 0x03,
39            AddressType::IPv6 => 0x04,
40        }
41    }
42}
43
44/// SOCKS5 Address Format
45///
46/// ```plain
47/// +------+----------+----------+
48/// | ATYP | DST.ADDR | DST.PORT |
49/// +------+----------+----------+
50/// |  1   | Variable |    2     |
51/// +------+----------+----------+
52/// ```
53#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
54#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
55#[cfg_attr(feature = "serde", serde(try_from = "String", into = "String"))]
56pub enum Address {
57    /// Represents an IPv4 or IPv6 socket address.
58    SocketAddress(SocketAddr),
59    /// Represents a domain name and a port.
60    DomainAddress(Box<str>, u16),
61}
62
63impl Default for Address {
64    fn default() -> Self {
65        Address::unspecified()
66    }
67}
68
69impl Address {
70    /// Returns an unspecified IPv4 address (0.0.0.0:0).
71    pub fn unspecified() -> Self {
72        Address::SocketAddress(SocketAddr::from((Ipv4Addr::UNSPECIFIED, 0)))
73    }
74
75    /// Returns the type of the address (IPv4, IPv6, or Domain).
76    pub fn get_type(&self) -> AddressType {
77        match self {
78            Self::SocketAddress(SocketAddr::V4(_)) => AddressType::IPv4,
79            Self::SocketAddress(SocketAddr::V6(_)) => AddressType::IPv6,
80            Self::DomainAddress(_, _) => AddressType::Domain,
81        }
82    }
83
84    /// Returns the port number.
85    pub fn port(&self) -> u16 {
86        match self {
87            Self::SocketAddress(addr) => addr.port(),
88            Self::DomainAddress(_, port) => *port,
89        }
90    }
91
92    /// Returns the host name or IP address as a string.
93    pub fn host(&self) -> String {
94        match self {
95            Self::SocketAddress(addr) => addr.ip().to_string(),
96            Self::DomainAddress(addr, _) => addr.to_string(),
97        }
98    }
99
100    /// Returns the host name or IP address as a string.
101    #[deprecated(note = "use host() instead")]
102    pub fn domain(&self) -> String {
103        self.host()
104    }
105
106    /// Returns `true` if it is an IPv4 address.
107    pub fn is_ipv4(&self) -> bool {
108        matches!(self, Self::SocketAddress(SocketAddr::V4(_)))
109    }
110
111    /// Returns `true` if it is an IPv6 address.
112    pub fn is_ipv6(&self) -> bool {
113        matches!(self, Self::SocketAddress(SocketAddr::V6(_)))
114    }
115
116    /// Returns `true` if it is a domain address.
117    pub fn is_domain(&self) -> bool {
118        matches!(self, Self::DomainAddress(_, _))
119    }
120
121    /// Returns the maximum possible serialized length of a SOCKS5 address.
122    pub const fn max_serialized_len() -> usize {
123        1 + 1 + u8::MAX as usize + 2
124    }
125}
126
127impl StreamOperation for Address {
128    fn retrieve_from_stream<R: std::io::Read>(stream: &mut R) -> std::io::Result<Self> {
129        let mut atyp_buf = [0; 1];
130        stream.read_exact(&mut atyp_buf)?;
131        match AddressType::try_from(atyp_buf[0])? {
132            AddressType::IPv4 => {
133                let mut buf = [0; 6];
134                stream.read_exact(&mut buf)?;
135                let addr = Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]);
136                let port = u16::from_be_bytes([buf[4], buf[5]]);
137                Ok(Self::SocketAddress(SocketAddr::from((addr, port))))
138            }
139            AddressType::Domain => {
140                let mut len_buf = [0; 1];
141                stream.read_exact(&mut len_buf)?;
142                let len = len_buf[0] as usize;
143                let mut domain_buf = vec![0; len];
144                stream.read_exact(&mut domain_buf)?;
145
146                let mut port_buf = [0; 2];
147                stream.read_exact(&mut port_buf)?;
148                let port = u16::from_be_bytes(port_buf);
149
150                let addr = String::from_utf8(domain_buf)
151                    .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Invalid address encoding: {err}")))?;
152                Ok(Self::DomainAddress(addr.into_boxed_str(), port))
153            }
154            AddressType::IPv6 => {
155                let mut buf = [0; 18];
156                stream.read_exact(&mut buf)?;
157                let port = u16::from_be_bytes([buf[16], buf[17]]);
158                let mut addr_bytes = [0; 16];
159                addr_bytes.copy_from_slice(&buf[..16]);
160                Ok(Self::SocketAddress(SocketAddr::from((Ipv6Addr::from(addr_bytes), port))))
161            }
162        }
163    }
164
165    fn write_to_buf<B: BufMut>(&self, buf: &mut B) {
166        match self {
167            Self::SocketAddress(SocketAddr::V4(addr)) => {
168                buf.put_u8(AddressType::IPv4.into());
169                buf.put_slice(&addr.ip().octets());
170                buf.put_u16(addr.port());
171            }
172            Self::SocketAddress(SocketAddr::V6(addr)) => {
173                buf.put_u8(AddressType::IPv6.into());
174                buf.put_slice(&addr.ip().octets());
175                buf.put_u16(addr.port());
176            }
177            Self::DomainAddress(addr, port) => {
178                let addr = addr.as_bytes();
179                buf.put_u8(AddressType::Domain.into());
180                buf.put_u8(u8::try_from(addr.len()).expect("domain address too long for SOCKS5"));
181                buf.put_slice(addr);
182                buf.put_u16(*port);
183            }
184        }
185    }
186
187    fn len(&self) -> usize {
188        match self {
189            Address::SocketAddress(SocketAddr::V4(_)) => 1 + 4 + 2,
190            Address::SocketAddress(SocketAddr::V6(_)) => 1 + 16 + 2,
191            Address::DomainAddress(addr, _) => 1 + 1 + addr.len() + 2,
192        }
193    }
194}
195
196#[cfg(feature = "tokio")]
197#[async_trait::async_trait]
198impl AsyncStreamOperation for Address {
199    async fn retrieve_from_async_stream<R>(stream: &mut R) -> std::io::Result<Self>
200    where
201        R: AsyncRead + Unpin + Send + ?Sized,
202    {
203        let atyp = stream.read_u8().await?;
204        match AddressType::try_from(atyp)? {
205            AddressType::IPv4 => {
206                let mut addr_bytes = [0; 4];
207                stream.read_exact(&mut addr_bytes).await?;
208                let port = stream.read_u16().await?;
209                let addr = Ipv4Addr::from(addr_bytes);
210                Ok(Self::SocketAddress(SocketAddr::from((addr, port))))
211            }
212            AddressType::Domain => {
213                let len = stream.read_u8().await? as usize;
214                let mut domain_buf = vec![0; len];
215                stream.read_exact(&mut domain_buf).await?;
216                let port = stream.read_u16().await?;
217
218                let addr = String::from_utf8(domain_buf)
219                    .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Invalid address encoding: {err}")))?;
220                Ok(Self::DomainAddress(addr.into_boxed_str(), port))
221            }
222            AddressType::IPv6 => {
223                let mut addr_bytes = [0; 16];
224                stream.read_exact(&mut addr_bytes).await?;
225                let port = stream.read_u16().await?;
226                Ok(Self::SocketAddress(SocketAddr::from((Ipv6Addr::from(addr_bytes), port))))
227            }
228        }
229    }
230}
231
232impl ToSocketAddrs for Address {
233    type Iter = std::vec::IntoIter<SocketAddr>;
234
235    fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
236        match self {
237            Address::SocketAddress(addr) => Ok(vec![*addr].into_iter()),
238            Address::DomainAddress(addr, port) => Ok((&**addr, *port).to_socket_addrs()?),
239        }
240    }
241}
242
243impl std::fmt::Display for Address {
244    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245        match self {
246            Address::DomainAddress(hostname, port) => write!(f, "{hostname}:{port}"),
247            Address::SocketAddress(socket_addr) => write!(f, "{socket_addr}"),
248        }
249    }
250}
251
252impl TryFrom<String> for Address {
253    type Error = crate::Error;
254
255    fn try_from(addr: String) -> std::result::Result<Self, Self::Error> {
256        Self::try_from(addr.as_str())
257    }
258}
259
260impl TryFrom<&String> for Address {
261    type Error = crate::Error;
262
263    fn try_from(addr: &String) -> std::result::Result<Self, Self::Error> {
264        Self::try_from(addr.as_str())
265    }
266}
267
268impl From<Address> for String {
269    fn from(addr: Address) -> Self {
270        addr.to_string()
271    }
272}
273
274impl From<&Address> for String {
275    fn from(addr: &Address) -> Self {
276        addr.to_string()
277    }
278}
279
280impl TryFrom<Address> for SocketAddr {
281    type Error = std::io::Error;
282
283    fn try_from(address: Address) -> std::result::Result<Self, Self::Error> {
284        match address {
285            Address::SocketAddress(addr) => Ok(addr),
286            Address::DomainAddress(addr, port) => {
287                let addr = addr.as_ref();
288                if let Ok(addr) = addr.parse::<IpAddr>() {
289                    Ok(SocketAddr::from((addr, port)))
290                } else {
291                    let err = format!("domain address {addr} cannot be converted to a SocketAddr without DNS, use to_socket_addrs instead");
292                    Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, err))
293                }
294            }
295        }
296    }
297}
298
299impl TryFrom<&Address> for SocketAddr {
300    type Error = std::io::Error;
301
302    fn try_from(address: &Address) -> std::result::Result<Self, Self::Error> {
303        TryFrom::<Address>::try_from(address.clone())
304    }
305}
306
307impl From<Address> for Vec<u8> {
308    fn from(addr: Address) -> Self {
309        let mut buf = Vec::with_capacity(addr.len());
310        addr.write_to_buf(&mut buf);
311        buf
312    }
313}
314
315impl TryFrom<Vec<u8>> for Address {
316    type Error = std::io::Error;
317
318    fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
319        let mut rdr = Cursor::new(data);
320        Self::retrieve_from_stream(&mut rdr)
321    }
322}
323
324impl TryFrom<&[u8]> for Address {
325    type Error = std::io::Error;
326
327    fn try_from(data: &[u8]) -> std::result::Result<Self, Self::Error> {
328        let mut rdr = Cursor::new(data);
329        Self::retrieve_from_stream(&mut rdr)
330    }
331}
332
333impl From<SocketAddr> for Address {
334    fn from(addr: SocketAddr) -> Self {
335        Address::SocketAddress(addr)
336    }
337}
338
339impl From<&SocketAddr> for Address {
340    fn from(addr: &SocketAddr) -> Self {
341        Address::SocketAddress(*addr)
342    }
343}
344
345impl From<(Ipv4Addr, u16)> for Address {
346    fn from((addr, port): (Ipv4Addr, u16)) -> Self {
347        Address::SocketAddress(SocketAddr::from((addr, port)))
348    }
349}
350
351impl From<(Ipv6Addr, u16)> for Address {
352    fn from((addr, port): (Ipv6Addr, u16)) -> Self {
353        Address::SocketAddress(SocketAddr::from((addr, port)))
354    }
355}
356
357impl From<(IpAddr, u16)> for Address {
358    fn from((addr, port): (IpAddr, u16)) -> Self {
359        Address::SocketAddress(SocketAddr::from((addr, port)))
360    }
361}
362
363impl From<(String, u16)> for Address {
364    fn from((addr, port): (String, u16)) -> Self {
365        Address::from((addr.as_str(), port))
366    }
367}
368
369impl From<(&String, u16)> for Address {
370    fn from((addr, port): (&String, u16)) -> Self {
371        Address::from((addr.as_str(), port))
372    }
373}
374
375impl From<(&str, u16)> for Address {
376    fn from((addr, port): (&str, u16)) -> Self {
377        if let Ok(addr) = addr.parse::<IpAddr>() {
378            return Address::SocketAddress(SocketAddr::from((addr, port)));
379        }
380        Address::DomainAddress(addr.into(), port)
381    }
382}
383
384impl From<&Address> for Address {
385    fn from(addr: &Address) -> Self {
386        addr.clone()
387    }
388}
389
390impl TryFrom<&str> for Address {
391    type Error = crate::Error;
392
393    fn try_from(addr: &str) -> std::result::Result<Self, Self::Error> {
394        if let Ok(addr) = addr.parse::<SocketAddr>() {
395            Ok(Address::SocketAddress(addr))
396        } else {
397            if addr.matches(':').count() > 1 {
398                let err = format!("invalid socket address format: {addr}");
399                return Err(crate::Error::InvalidAddress(err));
400            }
401
402            let Some(pos) = addr.rfind(':') else {
403                let err = format!("missing port in address: {addr}");
404                return Err(crate::Error::InvalidAddress(err));
405            };
406
407            let (addr, port) = (&addr[..pos], &addr[pos + 1..]);
408            let port = port.parse::<u16>()?;
409            Ok(Address::from((addr, port)))
410        }
411    }
412}
413
414impl std::str::FromStr for Address {
415    type Err = crate::Error;
416
417    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
418        Self::try_from(s)
419    }
420}
421
422#[test]
423fn test_address() {
424    let addr = Address::from((Ipv4Addr::new(127, 0, 0, 1), 8080));
425    let mut buf = Vec::new();
426    addr.write_to_buf(&mut buf);
427    assert_eq!(buf, vec![0x01, 127, 0, 0, 1, 0x1f, 0x90]);
428    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
429    assert_eq!(addr, addr2);
430
431    let addr = Address::from((Ipv6Addr::new(0x45, 0xff89, 0, 0, 0, 0, 0, 1), 8080));
432    let mut buf = Vec::new();
433    addr.write_to_buf(&mut buf);
434    assert_eq!(buf, vec![0x04, 0, 0x45, 0xff, 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1f, 0x90]);
435    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
436    assert_eq!(addr, addr2);
437
438    let addr = Address::from(("sex.com", 8080));
439    let mut buf = Vec::new();
440    addr.write_to_buf(&mut buf);
441    assert_eq!(buf, vec![0x03, 0x07, b's', b'e', b'x', b'.', b'c', b'o', b'm', 0x1f, 0x90]);
442    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
443    assert_eq!(addr, addr2);
444
445    let addr = Address::try_from("example.com:8080").unwrap();
446    assert_eq!(addr.host(), "example.com");
447    assert!(Address::try_from("example.com").is_err());
448
449    let addr = Address::try_from("123.45.67.89:8080").unwrap();
450    assert!(addr.is_ipv4());
451    assert!(Address::try_from("123.45.67.89").is_err());
452
453    let addr = Address::try_from("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080").unwrap();
454    assert_eq!(addr.host(), "2001:db8:85a3::8a2e:370:7334");
455    assert!(addr.is_ipv6());
456
457    let addr = Address::from((Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080));
458    assert_eq!(addr.host(), "2001:db8::1");
459
460    assert!(Address::try_from("2001:0db8:85a3:0000:0000:8a2e:0370:7334:8080").is_err());
461}
462
463#[test]
464fn test_address_display_for_ipv6() {
465    let addr = Address::from((Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080));
466    assert_eq!(addr.to_string(), "[2001:db8::1]:8080");
467}
468
469#[cfg(feature = "serde")]
470#[test]
471fn test_address_serde_string_roundtrip() {
472    for value in ["127.0.0.1:8080", "example.com:8080", "[2001:db8::1]:8080"] {
473        let address = value.parse::<Address>().unwrap();
474        let serialized = serde_json::to_string(&address).unwrap();
475
476        assert_eq!(serialized, serde_json::to_string(&address.to_string()).unwrap());
477        assert_eq!(serde_json::from_str::<Address>(&serialized).unwrap(), address);
478    }
479    assert!(serde_json::from_str::<Address>(r#""example.com""#).is_err());
480}
481
482#[test]
483fn test_try_from_address_for_socketaddr() {
484    let addr = Address::from((Ipv4Addr::new(127, 0, 0, 1), 8080));
485    let socket_addr = SocketAddr::try_from(addr.clone()).unwrap();
486    assert_eq!(socket_addr, SocketAddr::from(([127, 0, 0, 1], 8080)));
487
488    let addr = Address::from(("192.168.1.1", 8080));
489    let socket_addr = SocketAddr::try_from(addr).unwrap();
490    assert_eq!(socket_addr, SocketAddr::from(([192, 168, 1, 1], 8080)));
491
492    let addr = Address::from(("example.com", 8080));
493    let err = SocketAddr::try_from(addr).unwrap_err();
494    assert!(format!("{err}").contains("cannot be converted to a SocketAddr without DNS"));
495
496    let addr = Address::from(("baidu.com", 8080));
497    let err = SocketAddr::try_from(addr).unwrap_err();
498    assert!(format!("{err}").contains("cannot be converted to a SocketAddr without DNS"));
499
500    let addr = Address::from(("baidu.com", 8080));
501    let socket_addrs: Vec<SocketAddr> = addr.to_socket_addrs().unwrap().collect();
502    assert!(!socket_addrs.is_empty());
503}
504
505#[cfg(feature = "tokio")]
506#[tokio::test]
507async fn test_address_async() {
508    let addr = Address::from((Ipv4Addr::new(127, 0, 0, 1), 8080));
509    let mut buf = Vec::new();
510    addr.write_to_async_stream(&mut buf).await.unwrap();
511    assert_eq!(buf, vec![0x01, 127, 0, 0, 1, 0x1f, 0x90]);
512    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
513    assert_eq!(addr, addr2);
514
515    let addr = Address::from((Ipv6Addr::new(0x45, 0xff89, 0, 0, 0, 0, 0, 1), 8080));
516    let mut buf = Vec::new();
517    addr.write_to_async_stream(&mut buf).await.unwrap();
518    assert_eq!(buf, vec![0x04, 0, 0x45, 0xff, 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1f, 0x90]);
519    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
520    assert_eq!(addr, addr2);
521
522    let addr = Address::from(("sex.com", 8080));
523    let mut buf = Vec::new();
524    addr.write_to_async_stream(&mut buf).await.unwrap();
525    assert_eq!(buf, vec![0x03, 0x07, b's', b'e', b'x', b'.', b'c', b'o', b'm', 0x1f, 0x90]);
526    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
527    assert_eq!(addr, addr2);
528}