Fix SOCKS5 usage for IMAP

Connect to SOCKS5 server rather than target server
and send TCP connect command.
This commit is contained in:
link2xt
2023-01-18 10:12:18 +00:00
parent cf0349acc8
commit 42c709e7b1
4 changed files with 20 additions and 15 deletions

View File

@@ -9,6 +9,7 @@
unread messages increases #3959 unread messages increases #3959
- Fix Peerstate comparison #3962 - Fix Peerstate comparison #3962
- Log SOCKS5 configuration for IMAP like already done for SMTP #3964 - Log SOCKS5 configuration for IMAP like already done for SMTP #3964
- Fix SOCKS5 usage for IMAP #3965
### API-Changes ### API-Changes
- jsonrpc: add verified-by information to `Contact`-Object - jsonrpc: add verified-by information to `Contact`-Object

View File

@@ -315,7 +315,7 @@ impl Imap {
) )
.await .await
} else { } else {
Client::connect_insecure_socks5((imap_server, imap_port), socks5_config.clone()) Client::connect_insecure_socks5(imap_server, imap_port, socks5_config.clone())
.await .await
} }
} else if config.lp.security == Socket::Starttls { } else if config.lp.security == Socket::Starttls {

View File

@@ -124,8 +124,7 @@ impl Client {
let tcp_stream = connect_tcp((hostname, port), IMAP_TIMEOUT).await?; let tcp_stream = connect_tcp((hostname, port), IMAP_TIMEOUT).await?;
// Run STARTTLS command and convert the client back into a stream. // Run STARTTLS command and convert the client back into a stream.
let session_stream: Box<dyn SessionStream> = Box::new(tcp_stream); let mut client = ImapClient::new(tcp_stream);
let mut client = ImapClient::new(session_stream);
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await
@@ -155,7 +154,7 @@ impl Client {
strict_tls: bool, strict_tls: bool,
socks5_config: Socks5Config, socks5_config: Socks5Config,
) -> Result<Self> { ) -> Result<Self> {
let socks5_stream = socks5_config.connect((domain, port), IMAP_TIMEOUT).await?; let socks5_stream = socks5_config.connect(domain, port, IMAP_TIMEOUT).await?;
let tls = build_tls(strict_tls); let tls = build_tls(strict_tls);
let tls_stream = tls.connect(domain, socks5_stream).await?; let tls_stream = tls.connect(domain, socks5_stream).await?;
let buffered_stream = BufWriter::new(tls_stream); let buffered_stream = BufWriter::new(tls_stream);
@@ -170,10 +169,11 @@ impl Client {
} }
pub async fn connect_insecure_socks5( pub async fn connect_insecure_socks5(
target_addr: impl ToSocketAddrs, domain: &str,
port: u16,
socks5_config: Socks5Config, socks5_config: Socks5Config,
) -> Result<Self> { ) -> Result<Self> {
let socks5_stream = socks5_config.connect(target_addr, IMAP_TIMEOUT).await?; let socks5_stream = socks5_config.connect(domain, port, IMAP_TIMEOUT).await?;
let buffered_stream = BufWriter::new(socks5_stream); let buffered_stream = BufWriter::new(socks5_stream);
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream); let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
let mut client = ImapClient::new(session_stream); let mut client = ImapClient::new(session_stream);
@@ -191,13 +191,10 @@ impl Client {
socks5_config: Socks5Config, socks5_config: Socks5Config,
strict_tls: bool, strict_tls: bool,
) -> Result<Self> { ) -> Result<Self> {
let socks5_stream = socks5_config let socks5_stream = socks5_config.connect(hostname, port, IMAP_TIMEOUT).await?;
.connect((hostname, port), IMAP_TIMEOUT)
.await?;
// Run STARTTLS command and convert the client back into a stream. // Run STARTTLS command and convert the client back into a stream.
let session_stream: Box<dyn SessionStream> = Box::new(socks5_stream); let mut client = ImapClient::new(socks5_stream);
let mut client = ImapClient::new(session_stream);
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await

View File

@@ -7,12 +7,14 @@ use std::time::Duration;
use crate::net::connect_tcp; use crate::net::connect_tcp;
use anyhow::Result; use anyhow::Result;
pub use async_smtp::ServerAddress; pub use async_smtp::ServerAddress;
use tokio::net::{self, TcpStream}; use tokio::net::TcpStream;
use tokio_io_timeout::TimeoutStream; use tokio_io_timeout::TimeoutStream;
use crate::context::Context; use crate::context::Context;
use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::client::{Config, Socks5Stream};
use fast_socks5::util::target_addr::ToTargetAddr;
use fast_socks5::AuthenticationMethod; use fast_socks5::AuthenticationMethod;
use fast_socks5::Socks5Command;
#[derive(Default, Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Socks5Config { pub struct Socks5Config {
@@ -56,10 +58,11 @@ impl Socks5Config {
pub async fn connect( pub async fn connect(
&self, &self,
target_addr: impl net::ToSocketAddrs, target_host: &str,
target_port: u16,
timeout_val: Duration, timeout_val: Duration,
) -> Result<Socks5Stream<Pin<Box<TimeoutStream<TcpStream>>>>> { ) -> Result<Socks5Stream<Pin<Box<TimeoutStream<TcpStream>>>>> {
let tcp_stream = connect_tcp(target_addr, timeout_val).await?; let tcp_stream = connect_tcp((self.host.clone(), self.port), timeout_val).await?;
let authentication_method = if let Some((username, password)) = self.user_password.as_ref() let authentication_method = if let Some((username, password)) = self.user_password.as_ref()
{ {
@@ -70,8 +73,12 @@ impl Socks5Config {
} else { } else {
None None
}; };
let socks_stream = let mut socks_stream =
Socks5Stream::use_stream(tcp_stream, authentication_method, Config::default()).await?; Socks5Stream::use_stream(tcp_stream, authentication_method, Config::default()).await?;
let target_addr = (target_host, target_port).to_target_addr()?;
socks_stream
.request(Socks5Command::TCPConnect, target_addr)
.await?;
Ok(socks_stream) Ok(socks_stream)
} }