mirror of
https://github.com/house-of-vanity/v2-uri-parser.git
synced 2025-12-16 06:57:52 +00:00
Merge pull request #12 from Keivan-sf/5-improve-vless-parser-and-headers
sync
This commit is contained in:
@@ -9,10 +9,11 @@ V2ray URI parser
|
|||||||
Usage: v2parser [OPTIONS] <URI>
|
Usage: v2parser [OPTIONS] <URI>
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
<URI>
|
<URI>
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-s, --socksport <socksport>
|
--socksport <socksport>
|
||||||
|
--httpport <httpport>
|
||||||
-h, --help Print help
|
-h, --help Print help
|
||||||
-V, --version Print version
|
-V, --version Print version
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ pub struct WsSettings {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TlsSettings {
|
pub struct TlsSettings {
|
||||||
pub alpn: Option<Vec<String>>,
|
pub alpn: Option<Vec<String>>,
|
||||||
pub allowInsecure: Option<bool>,
|
pub allowInsecure: bool,
|
||||||
pub serverName: Option<String>,
|
pub serverName: Option<String>,
|
||||||
pub enableSessionResumption: Option<bool>,
|
pub enableSessionResumption: Option<bool>,
|
||||||
pub disableSystemRoot: Option<bool>,
|
pub disableSystemRoot: Option<bool>,
|
||||||
@@ -165,7 +165,7 @@ pub struct Inbound {
|
|||||||
pub listen: String,
|
pub listen: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub protocol: String,
|
pub protocol: String,
|
||||||
pub settings: InboundSettings,
|
pub settings: Option<InboundSettings>,
|
||||||
pub sniffing: Option<SniffingSettings>,
|
pub sniffing: Option<SniffingSettings>,
|
||||||
pub tag: String,
|
pub tag: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ pub mod utils;
|
|||||||
#[command(author ,version = "0.1.1", about = "V2ray URI parser", long_about = None)]
|
#[command(author ,version = "0.1.1", about = "V2ray URI parser", long_about = None)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
uri: String,
|
uri: String,
|
||||||
#[arg(short, long, value_name = "socksport")]
|
#[arg(long, value_name = "socksport")]
|
||||||
socksport: Option<u16>,
|
socksport: Option<u16>,
|
||||||
|
#[arg(long, value_name = "httpport")]
|
||||||
|
httpport: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let json_config = parser::create_json_config(&cli.uri, cli.socksport);
|
let json_config = parser::create_json_config(&cli.uri, cli.socksport, cli.httpport);
|
||||||
println!("{}", json_config);
|
println!("{}", json_config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,22 @@ use std::process::exit;
|
|||||||
mod uri_identifier;
|
mod uri_identifier;
|
||||||
mod vless;
|
mod vless;
|
||||||
|
|
||||||
pub fn create_json_config(uri: &str, socks_port: Option<u16>) -> String {
|
pub fn create_json_config(uri: &str, socks_port: Option<u16>, http_port: Option<u16>) -> String {
|
||||||
let config = create_config(uri, socks_port);
|
let config = create_config(uri, socks_port, http_port);
|
||||||
let serialized = serde_json::to_string(&config).unwrap();
|
let serialized = serde_json::to_string(&config).unwrap();
|
||||||
return serialized;
|
return serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_config(uri: &str, socks_port: Option<u16>) -> config_models::Config {
|
pub fn create_config(
|
||||||
|
uri: &str,
|
||||||
|
socks_port: Option<u16>,
|
||||||
|
http_port: Option<u16>,
|
||||||
|
) -> config_models::Config {
|
||||||
let outbound_object = create_outbound_object(uri);
|
let outbound_object = create_outbound_object(uri);
|
||||||
let inbound_config =
|
let inbound_config =
|
||||||
inbound_generator::generate_inbound_config(inbound_generator::InboundGenerationOptions {
|
inbound_generator::generate_inbound_config(inbound_generator::InboundGenerationOptions {
|
||||||
socks_port,
|
socks_port,
|
||||||
|
http_port,
|
||||||
});
|
});
|
||||||
let config = config_models::Config {
|
let config = config_models::Config {
|
||||||
outbounds: vec![outbound_object],
|
outbounds: vec![outbound_object],
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ fn parse_vless_query(raw_query: &str) -> models::VlessQuery {
|
|||||||
slpn: get_parameter_value(&query, "slpn"),
|
slpn: get_parameter_value(&query, "slpn"),
|
||||||
spx: url_decode(get_parameter_value(&query, "spx")),
|
spx: url_decode(get_parameter_value(&query, "spx")),
|
||||||
extra: url_decode(get_parameter_value(&query, "extra")),
|
extra: url_decode(get_parameter_value(&query, "extra")),
|
||||||
|
allowInsecure: get_parameter_value(&query, "allowInsecure"),
|
||||||
};
|
};
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,17 @@ use crate::{config_models::*, utils::parse_raw_json};
|
|||||||
|
|
||||||
pub fn create_outbound_object(data: models::VlessData) -> Outbound {
|
pub fn create_outbound_object(data: models::VlessData) -> Outbound {
|
||||||
let network_type = data.query.r#type.clone().unwrap_or(String::from(""));
|
let network_type = data.query.r#type.clone().unwrap_or(String::from(""));
|
||||||
|
|
||||||
|
let allow_insecure = data.query.allowInsecure == Some(String::from("true"))
|
||||||
|
|| data.query.allowInsecure == Some(String::from("1"));
|
||||||
|
|
||||||
return Outbound {
|
return Outbound {
|
||||||
protocol: String::from("vless"),
|
protocol: String::from("vless"),
|
||||||
tag: String::from("proxy"),
|
tag: String::from("proxy"),
|
||||||
streamSettings: StreamSettings {
|
streamSettings: StreamSettings {
|
||||||
network: data.query.r#type.clone(),
|
network: data.query.r#type.clone(),
|
||||||
security: data.query.security.clone(),
|
security: data.query.security.clone(),
|
||||||
tlsSettings: if network_type == String::from("tls") {
|
tlsSettings: if data.query.security == Some(String::from("tls")) {
|
||||||
Some(TlsSettings {
|
Some(TlsSettings {
|
||||||
alpn: data.query.alpn.map(|alpn| vec![alpn]),
|
alpn: data.query.alpn.map(|alpn| vec![alpn]),
|
||||||
rejectUnknownSni: None,
|
rejectUnknownSni: None,
|
||||||
@@ -22,7 +26,7 @@ pub fn create_outbound_object(data: models::VlessData) -> Outbound {
|
|||||||
preferServerCipherSuites: None,
|
preferServerCipherSuites: None,
|
||||||
fingerprint: data.query.fp.clone(),
|
fingerprint: data.query.fp.clone(),
|
||||||
serverName: data.query.sni.clone(),
|
serverName: data.query.sni.clone(),
|
||||||
allowInsecure: Some(false),
|
allowInsecure: allow_insecure,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#[allow(non_snake_case)]
|
||||||
pub struct VlessQuery {
|
pub struct VlessQuery {
|
||||||
pub security: Option<String>,
|
pub security: Option<String>,
|
||||||
pub sni: Option<String>,
|
pub sni: Option<String>,
|
||||||
@@ -20,6 +21,7 @@ pub struct VlessQuery {
|
|||||||
pub spx: Option<String>,
|
pub spx: Option<String>,
|
||||||
pub alpn: Option<String>,
|
pub alpn: Option<String>,
|
||||||
pub extra: Option<String>,
|
pub extra: Option<String>,
|
||||||
|
pub allowInsecure: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VlessAddress {
|
pub struct VlessAddress {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::config_models;
|
|||||||
|
|
||||||
pub struct InboundGenerationOptions {
|
pub struct InboundGenerationOptions {
|
||||||
pub socks_port: Option<u16>,
|
pub socks_port: Option<u16>,
|
||||||
|
pub http_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_inbound_config(options: InboundGenerationOptions) -> Vec<config_models::Inbound> {
|
pub fn generate_inbound_config(options: InboundGenerationOptions) -> Vec<config_models::Inbound> {
|
||||||
@@ -12,16 +13,24 @@ pub fn generate_inbound_config(options: InboundGenerationOptions) -> Vec<config_
|
|||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match options.http_port {
|
||||||
|
Some(port) => {
|
||||||
|
inbounds.push(generate_http_inbound(port));
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
return inbounds;
|
return inbounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_socks_inbound(socks_port: u16) -> config_models::Inbound {
|
pub fn generate_http_inbound(http_port: u16) -> config_models::Inbound {
|
||||||
return config_models::Inbound {
|
return config_models::Inbound {
|
||||||
protocol: String::from("socks"),
|
protocol: String::from("http"),
|
||||||
port: socks_port,
|
port: http_port,
|
||||||
tag: String::from("socks-in"),
|
tag: String::from("http-in"),
|
||||||
|
settings: None,
|
||||||
listen: String::from("127.0.0.1"),
|
listen: String::from("127.0.0.1"),
|
||||||
settings: config_models::InboundSettings { udp: true },
|
|
||||||
sniffing: Some(config_models::SniffingSettings {
|
sniffing: Some(config_models::SniffingSettings {
|
||||||
enabled: Some(true),
|
enabled: Some(true),
|
||||||
routeOnly: Some(true),
|
routeOnly: Some(true),
|
||||||
@@ -36,29 +45,23 @@ pub fn generate_socks_inbound(socks_port: u16) -> config_models::Inbound {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
pub fn generate_socks_inbound(socks_port: u16) -> config_models::Inbound {
|
||||||
mod test {
|
return config_models::Inbound {
|
||||||
use super::*;
|
protocol: String::from("socks"),
|
||||||
#[test]
|
port: socks_port,
|
||||||
fn test_generate_socks_inboud() {
|
tag: String::from("socks-in"),
|
||||||
let socks_inbound = generate_socks_inbound(2080);
|
listen: String::from("127.0.0.1"),
|
||||||
assert_eq!(socks_inbound.protocol, String::from("socks"));
|
settings: Some(config_models::InboundSettings { udp: true }),
|
||||||
assert_eq!(socks_inbound.listen, String::from("127.0.0.1"));
|
sniffing: Some(config_models::SniffingSettings {
|
||||||
assert_eq!(socks_inbound.tag, String::from("socks-in"));
|
enabled: Some(true),
|
||||||
assert_eq!(socks_inbound.port, 2080);
|
routeOnly: Some(true),
|
||||||
assert_eq!(socks_inbound.settings.udp, true);
|
metadataOnly: Some(false),
|
||||||
|
domainsExcluded: None,
|
||||||
let sniffing_obj = socks_inbound.sniffing.unwrap();
|
destOverride: Some(vec![
|
||||||
assert_eq!(sniffing_obj.enabled, Some(true));
|
|
||||||
assert_eq!(sniffing_obj.routeOnly, Some(true));
|
|
||||||
assert_eq!(sniffing_obj.domainsExcluded, None);
|
|
||||||
assert_eq!(
|
|
||||||
sniffing_obj.destOverride,
|
|
||||||
Some(vec![
|
|
||||||
String::from("http"),
|
String::from("http"),
|
||||||
String::from("tls"),
|
String::from("tls"),
|
||||||
String::from("quic"),
|
String::from("quic"),
|
||||||
])
|
]),
|
||||||
);
|
}),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user