Skip to main content

socks5_impl/protocol/
address.rs

1#[cfg(feature = "tokio")]
2use crate::protocol::AsyncStreamOperation;
3use crate::protocol::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))]
55pub enum Address {
56    /// Represents an IPv4 or IPv6 socket address.
57    SocketAddress(SocketAddr),
58    /// Represents a domain name and a port.
59    DomainAddress(Box<str>, u16),
60}
61
62impl Default for Address {
63    fn default() -> Self {
64        Address::unspecified()
65    }
66}
67
68impl Address {
69    /// Returns an unspecified IPv4 address (0.0.0.0:0).
70    pub fn unspecified() -> Self {
71        Address::SocketAddress(SocketAddr::from((Ipv4Addr::UNSPECIFIED, 0)))
72    }
73
74    /// Returns the type of the address (IPv4, IPv6, or Domain).
75    pub fn get_type(&self) -> AddressType {
76        match self {
77            Self::SocketAddress(SocketAddr::V4(_)) => AddressType::IPv4,
78            Self::SocketAddress(SocketAddr::V6(_)) => AddressType::IPv6,
79            Self::DomainAddress(_, _) => AddressType::Domain,
80        }
81    }
82
83    /// Returns the port number.
84    pub fn port(&self) -> u16 {
85        match self {
86            Self::SocketAddress(addr) => addr.port(),
87            Self::DomainAddress(_, port) => *port,
88        }
89    }
90
91    /// Returns the domain name or IP address as a string.
92    pub fn domain(&self) -> String {
93        match self {
94            Self::SocketAddress(addr) => addr.ip().to_string(),
95            Self::DomainAddress(addr, _) => addr.to_string(),
96        }
97    }
98
99    /// Returns `true` if it is an IPv4 address.
100    pub fn is_ipv4(&self) -> bool {
101        matches!(self, Self::SocketAddress(SocketAddr::V4(_)))
102    }
103
104    /// Returns `true` if it is an IPv6 address.
105    pub fn is_ipv6(&self) -> bool {
106        matches!(self, Self::SocketAddress(SocketAddr::V6(_)))
107    }
108
109    /// Returns `true` if it is a domain address.
110    pub fn is_domain(&self) -> bool {
111        matches!(self, Self::DomainAddress(_, _))
112    }
113
114    /// Returns the maximum possible serialized length of a SOCKS5 address.
115    pub const fn max_serialized_len() -> usize {
116        1 + 1 + u8::MAX as usize + 2
117    }
118}
119
120impl StreamOperation for Address {
121    fn retrieve_from_stream<R: std::io::Read>(stream: &mut R) -> std::io::Result<Self> {
122        let mut atyp_buf = [0; 1];
123        stream.read_exact(&mut atyp_buf)?;
124        match AddressType::try_from(atyp_buf[0])? {
125            AddressType::IPv4 => {
126                let mut buf = [0; 6];
127                stream.read_exact(&mut buf)?;
128                let addr = Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]);
129                let port = u16::from_be_bytes([buf[4], buf[5]]);
130                Ok(Self::SocketAddress(SocketAddr::from((addr, port))))
131            }
132            AddressType::Domain => {
133                let mut len_buf = [0; 1];
134                stream.read_exact(&mut len_buf)?;
135                let len = len_buf[0] as usize;
136                let mut domain_buf = vec![0; len];
137                stream.read_exact(&mut domain_buf)?;
138
139                let mut port_buf = [0; 2];
140                stream.read_exact(&mut port_buf)?;
141                let port = u16::from_be_bytes(port_buf);
142
143                let addr = String::from_utf8(domain_buf)
144                    .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Invalid address encoding: {err}")))?;
145                Ok(Self::DomainAddress(addr.into_boxed_str(), port))
146            }
147            AddressType::IPv6 => {
148                let mut buf = [0; 18];
149                stream.read_exact(&mut buf)?;
150                let port = u16::from_be_bytes([buf[16], buf[17]]);
151                let mut addr_bytes = [0; 16];
152                addr_bytes.copy_from_slice(&buf[..16]);
153                Ok(Self::SocketAddress(SocketAddr::from((Ipv6Addr::from(addr_bytes), port))))
154            }
155        }
156    }
157
158    fn write_to_buf<B: BufMut>(&self, buf: &mut B) {
159        match self {
160            Self::SocketAddress(SocketAddr::V4(addr)) => {
161                buf.put_u8(AddressType::IPv4.into());
162                buf.put_slice(&addr.ip().octets());
163                buf.put_u16(addr.port());
164            }
165            Self::SocketAddress(SocketAddr::V6(addr)) => {
166                buf.put_u8(AddressType::IPv6.into());
167                buf.put_slice(&addr.ip().octets());
168                buf.put_u16(addr.port());
169            }
170            Self::DomainAddress(addr, port) => {
171                let addr = addr.as_bytes();
172                buf.put_u8(AddressType::Domain.into());
173                buf.put_u8(u8::try_from(addr.len()).expect("domain address too long for SOCKS5"));
174                buf.put_slice(addr);
175                buf.put_u16(*port);
176            }
177        }
178    }
179
180    fn len(&self) -> usize {
181        match self {
182            Address::SocketAddress(SocketAddr::V4(_)) => 1 + 4 + 2,
183            Address::SocketAddress(SocketAddr::V6(_)) => 1 + 16 + 2,
184            Address::DomainAddress(addr, _) => 1 + 1 + addr.len() + 2,
185        }
186    }
187}
188
189#[cfg(feature = "tokio")]
190#[async_trait::async_trait]
191impl AsyncStreamOperation for Address {
192    async fn retrieve_from_async_stream<R>(stream: &mut R) -> std::io::Result<Self>
193    where
194        R: AsyncRead + Unpin + Send + ?Sized,
195    {
196        let atyp = stream.read_u8().await?;
197        match AddressType::try_from(atyp)? {
198            AddressType::IPv4 => {
199                let mut addr_bytes = [0; 4];
200                stream.read_exact(&mut addr_bytes).await?;
201                let port = stream.read_u16().await?;
202                let addr = Ipv4Addr::from(addr_bytes);
203                Ok(Self::SocketAddress(SocketAddr::from((addr, port))))
204            }
205            AddressType::Domain => {
206                let len = stream.read_u8().await? as usize;
207                let mut domain_buf = vec![0; len];
208                stream.read_exact(&mut domain_buf).await?;
209                let port = stream.read_u16().await?;
210
211                let addr = String::from_utf8(domain_buf)
212                    .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("Invalid address encoding: {err}")))?;
213                Ok(Self::DomainAddress(addr.into_boxed_str(), port))
214            }
215            AddressType::IPv6 => {
216                let mut addr_bytes = [0; 16];
217                stream.read_exact(&mut addr_bytes).await?;
218                let port = stream.read_u16().await?;
219                Ok(Self::SocketAddress(SocketAddr::from((Ipv6Addr::from(addr_bytes), port))))
220            }
221        }
222    }
223}
224
225impl ToSocketAddrs for Address {
226    type Iter = std::vec::IntoIter<SocketAddr>;
227
228    fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
229        match self {
230            Address::SocketAddress(addr) => Ok(vec![*addr].into_iter()),
231            Address::DomainAddress(addr, port) => Ok((&**addr, *port).to_socket_addrs()?),
232        }
233    }
234}
235
236impl std::fmt::Display for Address {
237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238        match self {
239            Address::DomainAddress(hostname, port) => write!(f, "{hostname}:{port}"),
240            Address::SocketAddress(socket_addr) => write!(f, "{socket_addr}"),
241        }
242    }
243}
244
245impl TryFrom<Address> for SocketAddr {
246    type Error = std::io::Error;
247
248    fn try_from(address: Address) -> std::result::Result<Self, Self::Error> {
249        match address {
250            Address::SocketAddress(addr) => Ok(addr),
251            Address::DomainAddress(addr, port) => {
252                if let Ok(addr) = addr.parse::<Ipv4Addr>() {
253                    Ok(SocketAddr::from((addr, port)))
254                } else if let Ok(addr) = addr.parse::<Ipv6Addr>() {
255                    Ok(SocketAddr::from((addr, port)))
256                } else if let Ok(addr) = addr.parse::<SocketAddr>() {
257                    Ok(addr)
258                } else {
259                    let err = format!("domain address {addr} is not supported");
260                    Err(Self::Error::new(std::io::ErrorKind::Unsupported, err))
261                }
262            }
263        }
264    }
265}
266
267impl TryFrom<&Address> for SocketAddr {
268    type Error = std::io::Error;
269
270    fn try_from(address: &Address) -> std::result::Result<Self, Self::Error> {
271        TryFrom::<Address>::try_from(address.clone())
272    }
273}
274
275impl From<Address> for Vec<u8> {
276    fn from(addr: Address) -> Self {
277        let mut buf = Vec::with_capacity(addr.len());
278        addr.write_to_buf(&mut buf);
279        buf
280    }
281}
282
283impl TryFrom<Vec<u8>> for Address {
284    type Error = std::io::Error;
285
286    fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
287        let mut rdr = Cursor::new(data);
288        Self::retrieve_from_stream(&mut rdr)
289    }
290}
291
292impl TryFrom<&[u8]> for Address {
293    type Error = std::io::Error;
294
295    fn try_from(data: &[u8]) -> std::result::Result<Self, Self::Error> {
296        let mut rdr = Cursor::new(data);
297        Self::retrieve_from_stream(&mut rdr)
298    }
299}
300
301impl From<SocketAddr> for Address {
302    fn from(addr: SocketAddr) -> Self {
303        Address::SocketAddress(addr)
304    }
305}
306
307impl From<&SocketAddr> for Address {
308    fn from(addr: &SocketAddr) -> Self {
309        Address::SocketAddress(*addr)
310    }
311}
312
313impl From<(Ipv4Addr, u16)> for Address {
314    fn from((addr, port): (Ipv4Addr, u16)) -> Self {
315        Address::SocketAddress(SocketAddr::from((addr, port)))
316    }
317}
318
319impl From<(Ipv6Addr, u16)> for Address {
320    fn from((addr, port): (Ipv6Addr, u16)) -> Self {
321        Address::SocketAddress(SocketAddr::from((addr, port)))
322    }
323}
324
325impl From<(IpAddr, u16)> for Address {
326    fn from((addr, port): (IpAddr, u16)) -> Self {
327        Address::SocketAddress(SocketAddr::from((addr, port)))
328    }
329}
330
331impl From<(String, u16)> for Address {
332    fn from((addr, port): (String, u16)) -> Self {
333        Address::from((addr.as_str(), port))
334    }
335}
336
337impl From<(&String, u16)> for Address {
338    fn from((addr, port): (&String, u16)) -> Self {
339        Address::from((addr.as_str(), port))
340    }
341}
342
343impl From<(&str, u16)> for Address {
344    fn from((addr, port): (&str, u16)) -> Self {
345        if let Ok(addr) = addr.parse::<IpAddr>() {
346            return Address::SocketAddress(SocketAddr::from((addr, port)));
347        }
348        Address::DomainAddress(addr.into(), port)
349    }
350}
351
352impl From<&Address> for Address {
353    fn from(addr: &Address) -> Self {
354        addr.clone()
355    }
356}
357
358impl TryFrom<&str> for Address {
359    type Error = crate::Error;
360
361    fn try_from(addr: &str) -> std::result::Result<Self, Self::Error> {
362        if let Ok(addr) = addr.parse::<SocketAddr>() {
363            Ok(Address::SocketAddress(addr))
364        } else {
365            if addr.matches(':').count() > 1 {
366                let err = format!("invalid socket address format: {addr}");
367                return Err(crate::Error::InvalidAddress(err));
368            }
369
370            let Some(pos) = addr.rfind(':') else {
371                let err = format!("missing port in address: {addr}");
372                return Err(crate::Error::InvalidAddress(err));
373            };
374
375            let (addr, port) = (&addr[..pos], &addr[pos + 1..]);
376            let port = port.parse::<u16>()?;
377            Ok(Address::from((addr, port)))
378        }
379    }
380}
381
382impl std::str::FromStr for Address {
383    type Err = crate::Error;
384
385    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
386        Self::try_from(s)
387    }
388}
389
390#[test]
391fn test_address() {
392    let addr = Address::from((Ipv4Addr::new(127, 0, 0, 1), 8080));
393    let mut buf = Vec::new();
394    addr.write_to_buf(&mut buf);
395    assert_eq!(buf, vec![0x01, 127, 0, 0, 1, 0x1f, 0x90]);
396    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
397    assert_eq!(addr, addr2);
398
399    let addr = Address::from((Ipv6Addr::new(0x45, 0xff89, 0, 0, 0, 0, 0, 1), 8080));
400    let mut buf = Vec::new();
401    addr.write_to_buf(&mut buf);
402    assert_eq!(buf, vec![0x04, 0, 0x45, 0xff, 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1f, 0x90]);
403    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
404    assert_eq!(addr, addr2);
405
406    let addr = Address::from(("sex.com", 8080));
407    let mut buf = Vec::new();
408    addr.write_to_buf(&mut buf);
409    assert_eq!(buf, vec![0x03, 0x07, b's', b'e', b'x', b'.', b'c', b'o', b'm', 0x1f, 0x90]);
410    let addr2 = Address::retrieve_from_stream(&mut Cursor::new(&buf)).unwrap();
411    assert_eq!(addr, addr2);
412
413    let addr = Address::try_from("example.com:8080").unwrap();
414    assert_eq!(addr.domain(), "example.com");
415    assert!(Address::try_from("example.com").is_err());
416
417    let addr = Address::try_from("123.45.67.89:8080").unwrap();
418    assert!(addr.is_ipv4());
419    assert!(Address::try_from("123.45.67.89").is_err());
420
421    let addr = Address::try_from("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080").unwrap();
422    assert_eq!(addr.domain(), "2001:db8:85a3::8a2e:370:7334");
423    assert!(addr.is_ipv6());
424
425    assert!(Address::try_from("2001:0db8:85a3:0000:0000:8a2e:0370:7334:8080").is_err());
426}
427
428#[cfg(feature = "tokio")]
429#[tokio::test]
430async fn test_address_async() {
431    let addr = Address::from((Ipv4Addr::new(127, 0, 0, 1), 8080));
432    let mut buf = Vec::new();
433    addr.write_to_async_stream(&mut buf).await.unwrap();
434    assert_eq!(buf, vec![0x01, 127, 0, 0, 1, 0x1f, 0x90]);
435    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
436    assert_eq!(addr, addr2);
437
438    let addr = Address::from((Ipv6Addr::new(0x45, 0xff89, 0, 0, 0, 0, 0, 1), 8080));
439    let mut buf = Vec::new();
440    addr.write_to_async_stream(&mut buf).await.unwrap();
441    assert_eq!(buf, vec![0x04, 0, 0x45, 0xff, 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1f, 0x90]);
442    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
443    assert_eq!(addr, addr2);
444
445    let addr = Address::from(("sex.com", 8080));
446    let mut buf = Vec::new();
447    addr.write_to_async_stream(&mut buf).await.unwrap();
448    assert_eq!(buf, vec![0x03, 0x07, b's', b'e', b'x', b'.', b'c', b'o', b'm', 0x1f, 0x90]);
449    let addr2 = Address::retrieve_from_async_stream(&mut Cursor::new(&buf)).await.unwrap();
450    assert_eq!(addr, addr2);
451}