Skip to content

Commit

Permalink
feat: allow inbound bound to any address
Browse files Browse the repository at this point in the history
  • Loading branch information
XOR-op committed Jul 3, 2024
1 parent 8027681 commit 0bd8e8a
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 44 deletions.
27 changes: 18 additions & 9 deletions boltconn/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::config::{
safe_join_path, LinkedState, LoadedConfig, RawInboundServiceConfig, SingleOrVec,
default_inbound_ip_addr, safe_join_path, LinkedState, LoadedConfig, RawInboundServiceConfig,
SingleOrVec,
};
use crate::dispatch::{DispatchingBuilder, RuleSetBuilder};
use crate::external::{
Expand Down Expand Up @@ -253,14 +254,14 @@ impl App {
tokio::spawn(async move { tun.run(nat_addr).await });

// start http/socks5 inbound
for (port, http_auth, socks_auth) in
for (sock_addr, http_auth, socks_auth) in
parse_two_inbound_service(&config.inbound.http, &config.inbound.socks5)
{
let dispatcher = dispatcher.clone();
match (http_auth, socks_auth) {
(Some(http_auth), Some(socks_auth)) => {
tokio::spawn(async move {
MixedInbound::new(port, http_auth, socks_auth, dispatcher)
MixedInbound::new(sock_addr, http_auth, socks_auth, dispatcher)
.await?
.run()
.await;
Expand All @@ -269,13 +270,16 @@ impl App {
}
(Some(auth), None) => {
tokio::spawn(async move {
HttpInbound::new(port, auth, dispatcher).await?.run().await;
HttpInbound::new(sock_addr, auth, dispatcher)
.await?
.run()
.await;
Ok::<(), io::Error>(())
});
}
(None, Some(auth)) => {
tokio::spawn(async move {
Socks5Inbound::new(port, auth, dispatcher)
Socks5Inbound::new(sock_addr, auth, dispatcher)
.await?
.run()
.await;
Expand Down Expand Up @@ -438,22 +442,27 @@ fn parse_two_inbound_service(
http: &Option<SingleOrVec<RawInboundServiceConfig>>,
socks5: &Option<SingleOrVec<RawInboundServiceConfig>>,
) -> Vec<(
u16,
SocketAddr,
Option<HashMap<String, String>>,
Option<HashMap<String, String>>,
)> {
fn parse_inbound_service(
config: &Option<SingleOrVec<RawInboundServiceConfig>>,
) -> HashMap<u16, HashMap<String, String>> {
) -> HashMap<SocketAddr, HashMap<String, String>> {
config
.as_ref()
.map(|v| {
v.clone()
.linearize()
.into_iter()
.map(|c| match c {
RawInboundServiceConfig::Simple(p) => (p, HashMap::default()),
RawInboundServiceConfig::Complex { port, auth } => (port, auth),
RawInboundServiceConfig::Simple(p) => (
SocketAddr::new(default_inbound_ip_addr(), p),
HashMap::default(),
),
RawInboundServiceConfig::Complex { host, port, auth } => {
(SocketAddr::new(host, port), auth)
}
})
.collect()
})
Expand Down
4 changes: 2 additions & 2 deletions boltconn/src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub struct RawDnsConfig {
pub nameserver: Vec<String>,
#[serde(default = "default_hosts")]
pub hosts: HashMap<String, IpAddr>,
#[serde(alias = "nameserver-policy", default = "default_nameserver_policy")]
#[serde(alias = "nameserver-policy", default = "default_str_str_mapping")]
pub nameserver_policy: HashMap<String, String>,
}

Expand Down Expand Up @@ -191,7 +191,7 @@ fn default_hosts() -> HashMap<String, IpAddr> {
Default::default()
}

fn default_nameserver_policy() -> HashMap<String, String> {
pub(super) fn default_str_str_mapping() -> HashMap<String, String> {
Default::default()
}

Expand Down
27 changes: 24 additions & 3 deletions boltconn/src/config/inbound.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use super::config::default_true;
use crate::config::SingleOrVec;
use crate::config::{default_str_str_mapping, SingleOrVec};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::IpAddr;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum RawInboundServiceConfig {
Simple(u16),
Complex {
#[serde(default = "default_inbound_ip_addr")]
host: IpAddr,
port: u16,
#[serde(default = "default_str_str_mapping")]
auth: HashMap<String, String>,
},
}
Expand Down Expand Up @@ -40,6 +44,18 @@ http: 1080
socks5:
- 2000
- port: 8080
auth:
alice: bob
browser: none
";
let complex2 = "\
enable-tun: false
http: 1080
socks5:
- 2000
- host: 0.0.0.0
port: 8080
- port: 3000
auth:
alice: bob
browser: none
Expand All @@ -57,8 +73,13 @@ socks5:
let n: RawInboundConfig = serde_yaml::from_str(nothing).unwrap();
let s1: RawInboundConfig = serde_yaml::from_str(simple1).unwrap();
let s2: RawInboundConfig = serde_yaml::from_str(simple2).unwrap();
let c: RawInboundConfig = serde_yaml::from_str(complex).unwrap();
let c1: RawInboundConfig = serde_yaml::from_str(complex).unwrap();
let c2: RawInboundConfig = serde_yaml::from_str(complex2).unwrap();
let err: serde_yaml::Result<RawInboundConfig> = serde_yaml::from_str(fail);
assert!(err.is_err());
println!("{:?}\n{:?}\n{:?}\n{:?}", n, s1, s2, c);
println!("{:?}\n{:?}\n{:?}\n{:?}\n{:?}", n, s1, s2, c1, c2);
}

pub(crate) fn default_inbound_ip_addr() -> IpAddr {
"127.0.0.1".parse().unwrap()
}
20 changes: 12 additions & 8 deletions boltconn/src/proxy/http_inbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,48 @@ use base64::Engine;
use httparse::Request;
use std::collections::HashMap;
use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::SocketAddr;
use std::sync::atomic::AtomicU8;
use std::sync::Arc;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::{TcpListener, TcpStream};

pub struct HttpInbound {
port: u16,
sock_addr: SocketAddr,
server: TcpListener,
auth: Arc<HashMap<String, String>>,
dispatcher: Arc<Dispatcher>,
}

impl HttpInbound {
pub async fn new(
port: u16,
sock_addr: SocketAddr,
auth: HashMap<String, String>,
dispatcher: Arc<Dispatcher>,
) -> io::Result<Self> {
let server =
TcpListener::bind(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)).await?;
let server = TcpListener::bind(sock_addr).await?;
Ok(Self {
port,
sock_addr,
server,
auth: Arc::new(auth),
dispatcher,
})
}

pub async fn run(self) {
tracing::info!("[HTTP] Listen proxy at 127.0.0.1:{}, running...", self.port);
tracing::info!("[HTTP] Listen proxy at {}, running...", self.sock_addr);
loop {
match self.server.accept().await {
Ok((socket, addr)) => {
let disp = self.dispatcher.clone();
let auth = self.auth.clone();
tokio::spawn(Self::serve_connection(
self.port, socket, auth, addr, disp, None,
self.sock_addr.port(),
socket,
auth,
addr,
disp,
None,
));
}
Err(err) => {
Expand Down
23 changes: 12 additions & 11 deletions boltconn/src/proxy/mixed_inbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::proxy::error::TransportError;
use crate::proxy::{Dispatcher, HttpInbound, Socks5Inbound};
use std::collections::HashMap;
use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::io::AsyncReadExt;
use tokio::net::{TcpListener, TcpStream};

pub struct MixedInbound {
port: u16,
sock_addr: SocketAddr,
server: TcpListener,
http_auth: Arc<HashMap<String, String>>,
socks_auth: Arc<HashMap<String, String>>,
Expand All @@ -17,15 +17,14 @@ pub struct MixedInbound {

impl MixedInbound {
pub async fn new(
port: u16,
sock_addr: SocketAddr,
http_auth: HashMap<String, String>,
socks_auth: HashMap<String, String>,
dispatcher: Arc<Dispatcher>,
) -> io::Result<Self> {
let server =
TcpListener::bind(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)).await?;
let server = TcpListener::bind(sock_addr).await?;
Ok(Self {
port,
sock_addr,
server,
http_auth: Arc::new(http_auth),
socks_auth: Arc::new(socks_auth),
Expand All @@ -34,18 +33,20 @@ impl MixedInbound {
}

pub async fn run(self) {
tracing::info!(
"[Mixed] Listen proxy at 127.0.0.1:{}, running...",
self.port
);
tracing::info!("[Mixed] Listen proxy at {}, running...", self.sock_addr);
loop {
match self.server.accept().await {
Ok((socket, src_addr)) => {
let disp = self.dispatcher.clone();
let http_auth = self.http_auth.clone();
let socks_auth = self.socks_auth.clone();
tokio::spawn(Self::serve_connection(
self.port, socket, http_auth, socks_auth, src_addr, disp,
self.sock_addr.port(),
socket,
http_auth,
socks_auth,
src_addr,
disp,
));
}
Err(err) => {
Expand Down
23 changes: 12 additions & 11 deletions boltconn/src/proxy/socks5_inbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use fast_socks5::util::target_addr::{read_address, TargetAddr};
use fast_socks5::{consts, read_exact, ReplyError, SocksError};
use std::collections::HashMap;
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::Arc;
Expand All @@ -14,40 +14,41 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream, UdpSocket};

pub struct Socks5Inbound {
port: u16,
sock_addr: SocketAddr,
server: TcpListener,
auth: Arc<HashMap<String, String>>,
dispatcher: Arc<Dispatcher>,
}

impl Socks5Inbound {
pub async fn new(
port: u16,
sock_addr: SocketAddr,
auth: HashMap<String, String>,
dispatcher: Arc<Dispatcher>,
) -> io::Result<Self> {
let server =
TcpListener::bind(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)).await?;
let server = TcpListener::bind(sock_addr).await?;
Ok(Self {
port,
sock_addr,
server,
auth: Arc::new(auth),
dispatcher,
})
}

pub async fn run(self) {
tracing::info!(
"[Socks5] Listen proxy at 127.0.0.1:{}, running...",
self.port
);
tracing::info!("[Socks5] Listen proxy at {}, running...", self.sock_addr);
loop {
match self.server.accept().await {
Ok((socket, src_addr)) => {
let disp = self.dispatcher.clone();
let auth = self.auth.clone();
tokio::spawn(Self::serve_connection(
self.port, socket, auth, src_addr, disp, None,
self.sock_addr.port(),
socket,
auth,
src_addr,
disp,
None,
));
}
Err(err) => {
Expand Down

0 comments on commit 0bd8e8a

Please sign in to comment.