Browse Source

Merge pull request #13 from KaranGauswami/feature/clap_upgrade_v4

Feature/clap upgrade v4
pull/16/head
Karan Gauswami 2 years ago
committed by GitHub
parent
commit
72f3c19763
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      Cargo.lock
  2. 2
      Cargo.toml
  3. 22
      README.md
  4. 82
      src/main.rs

40
Cargo.lock

@ -106,26 +106,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.2.5"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.2.5"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck",
"proc-macro-error",
@ -136,9 +134,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.2.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
dependencies = [
"os_str_bytes",
]
@ -326,12 +324,6 @@ version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "hashbrown"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
[[package]]
name = "heck"
version = "0.4.0"
@ -444,16 +436,6 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -661,9 +643,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.39"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@ -823,12 +805,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "thiserror"
version = "1.0.31"

2
Cargo.toml

@ -15,7 +15,7 @@ color-eyre = { version = "0.5", default-features = false }
futures-util = "0.3"
http = "0.2"
hyper = { version = "0.14", features = ["http1", "server", "tcp", "client"] }
clap = { version = "3", features = ["derive"] }
clap = { version = "4", features = ["derive"] }
tokio-socks = "0.5"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
hyper-socks2 = { version = "0.6" }

22
README.md

@ -32,15 +32,15 @@ This will create proxy server on 8080 and use localhost:1080 as a Socks5 Proxy
There are a few options for using `sthp`.
```text
USAGE:
sthp [OPTIONS]
OPTIONS:
-h, --help Print help information
--listen-ip <LISTEN_IP> [default: 0.0.0.0]
-p, --port <PORT> port where Http proxy should listen [default: 8080]
-P, --password <PASSWORD> Socks5 password
-s, --socks-address <SOCKS_ADDRESS> Socks5 proxy address [default: 127.0.0.1:1080]
-u, --username <USERNAME> Socks5 username
-V, --version Print version information
Usage: sthp [OPTIONS]
Options:
-p, --port <PORT> port where Http proxy should listen [default: 8080]
--listen-ip <LISTEN_IP> [default: 0.0.0.0]
-u, --username <USERNAME> Socks5 username
-P, --password <PASSWORD> Socks5 password
-s, --socks-address <SOCKS_ADDRESS> Socks5 proxy address [default: 127.0.0.1:1080]
--allowed-domains <ALLOWED_DOMAINS> Comma-separated list of allowed domains
-h, --help Print help information
-V, --version Print version information
```

82
src/main.rs

@ -1,4 +1,6 @@
use clap::{ErrorKind, IntoApp, Parser};
#![deny(warnings)]
use clap::{Args, Parser};
use color_eyre::eyre::Result;
use http::Uri;
use hyper::client::HttpConnector;
@ -12,31 +14,38 @@ use std::net::{Ipv4Addr, SocketAddr};
use tokio_socks::tcp::Socks5Stream;
use tokio_socks::{IntoTargetAddr, ToProxyAddrs};
#[derive(Debug, Args)]
#[group()]
struct Auths {
/// Socks5 username
#[arg(short = 'u', long, required = false)]
username: String,
/// Socks5 password
#[arg(short = 'P', long, required = false)]
password: String,
}
#[derive(Parser, Debug)]
#[clap(author, version, about,long_about=None)]
#[command(author, version, about,long_about=None)]
struct Cli {
/// port where Http proxy should listen
#[clap(short, long, default_value = "8080",value_parser = clap::value_parser!(u16).range(1..))]
#[arg(short, long, default_value_t = 8080)]
port: u16,
#[clap(long, default_value = "0.0.0.0")]
#[arg(long, default_value = "0.0.0.0")]
listen_ip: Ipv4Addr,
#[command(flatten)]
auth: Option<Auths>,
/// Socks5 proxy address
#[clap(short, long, default_value = "127.0.0.1:1080")]
#[arg(short, long, default_value = "127.0.0.1:1080")]
socks_address: SocketAddr,
/// Socks5 username
#[clap(short = 'u', long)]
username: Option<String>,
/// Socks5 password
#[clap(short = 'P', long)]
password: Option<String>,
/// Comma-separated list of allowed domains
#[clap(long)]
allowed_domains: Option<String>,
#[arg(long, value_delimiter = ',')]
allowed_domains: Option<Vec<String>>,
}
#[tokio::main]
@ -48,27 +57,11 @@ async fn main() -> Result<()> {
let socks_address = args.socks_address;
let port = args.port;
let username = args.username;
let password = args.password;
let mut cmd = Cli::command();
let auth = match (username, password) {
(Some(username), Some(password)) => Some(Auth::new(username, password)),
(Some(_), None) => cmd
.error(
ErrorKind::ArgumentNotFound,
"--password is required if --username is used",
)
.exit(),
(None, Some(_)) => cmd
.error(
ErrorKind::ArgumentNotFound,
"--username is required if --password is used",
)
.exit(),
(None, None) => None,
};
let auth = args
.auth
.map(|auth| Auth::new(auth.username, auth.password));
let auth = &*Box::leak(Box::new(auth));
let addr = SocketAddr::from((args.listen_ip, port));
let mut connector = HttpConnector::new();
connector.enforce_http(false);
@ -80,10 +73,7 @@ async fn main() -> Result<()> {
};
let client: Client<SocksConnector<HttpConnector>> = hyper::Client::builder().build(connector);
let client = &*Box::leak(Box::new(client));
let allowed_domains = match args.allowed_domains {
Some(domains) => Some(domains.split(',').map(|d| d.trim().to_owned()).collect()),
None => None,
};
let allowed_domains = args.allowed_domains;
let allowed_domains = &*Box::leak(Box::new(allowed_domains));
let make_service = make_service_fn(move |_| async move {
Ok::<_, Infallible>(service_fn(move |req| {
@ -119,9 +109,17 @@ async fn proxy(
if let Some(plain) = host_addr(req.uri()) {
if let Some(allowed_domains) = allowed_domains {
let req_domain = req.uri().host().unwrap_or("").to_owned();
if !allowed_domains.iter().any(|domain| req_domain.ends_with(domain)) {
log::warn!("Access to domain {} is not allowed through the proxy.", req_domain);
let mut resp = Response::new(Body::from("Access to this domain is not allowed through the proxy."));
if !allowed_domains
.iter()
.any(|domain| req_domain.ends_with(domain))
{
log::warn!(
"Access to domain {} is not allowed through the proxy.",
req_domain
);
let mut resp = Response::new(Body::from(
"Access to this domain is not allowed through the proxy.",
));
*resp.status_mut() = http::StatusCode::FORBIDDEN;
return Ok(resp);
}

Loading…
Cancel
Save