Release MiniVLESS 0.1.0 for Linux
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
//! Local test server credentials only. Never accepts a real subscription on argv.
|
||||
use minivless::{
|
||||
config, guardian,
|
||||
storage::Preferences,
|
||||
tunnel::{AppState, Phase},
|
||||
vless,
|
||||
};
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
net::{SocketAddr, TcpStream, UdpSocket},
|
||||
path::{Path, PathBuf},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
fn main() {
|
||||
let a: Vec<String> = std::env::args().collect();
|
||||
if a.get(1).map(String::as_str) == Some("--core-guardian") {
|
||||
std::process::exit(guardian::run(Path::new(&a[2]), Path::new(&a[3])));
|
||||
}
|
||||
if a.get(1).map(String::as_str) == Some("--fetch") {
|
||||
let mut s = TcpStream::connect_timeout(
|
||||
&a[2].parse::<SocketAddr>().unwrap(),
|
||||
Duration::from_secs(4),
|
||||
)
|
||||
.unwrap();
|
||||
s.set_read_timeout(Some(Duration::from_secs(4))).unwrap();
|
||||
s.write_all(b"GET / HTTP/1.0\r\nHost: test\r\n\r\n")
|
||||
.unwrap();
|
||||
let mut text = String::new();
|
||||
s.read_to_string(&mut text).unwrap();
|
||||
println!("{}", text.split("\r\n\r\n").nth(1).unwrap());
|
||||
return;
|
||||
}
|
||||
if a.get(1).map(String::as_str) == Some("--dns") {
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
socket
|
||||
.set_read_timeout(Some(Duration::from_secs(5)))
|
||||
.unwrap();
|
||||
let query = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04test\x07example\x00\x00\x01\x00\x01";
|
||||
socket
|
||||
.send_to(query, a.get(2).map(String::as_str).unwrap_or("8.8.8.8:53"))
|
||||
.unwrap();
|
||||
let mut reply = [0; 512];
|
||||
let (n, _) = socket.recv_from(&mut reply).unwrap();
|
||||
assert!(n >= 4);
|
||||
println!(
|
||||
"{}.{}.{}.{}",
|
||||
reply[n - 4],
|
||||
reply[n - 3],
|
||||
reply[n - 2],
|
||||
reply[n - 1]
|
||||
);
|
||||
return;
|
||||
}
|
||||
if a.get(1).map(String::as_str) == Some("--udp") {
|
||||
let addr = a[2].parse::<SocketAddr>().unwrap();
|
||||
let socket = UdpSocket::bind(if addr.is_ipv6() {
|
||||
"[::]:0"
|
||||
} else {
|
||||
"0.0.0.0:0"
|
||||
})
|
||||
.unwrap();
|
||||
socket
|
||||
.set_read_timeout(Some(Duration::from_secs(4)))
|
||||
.unwrap();
|
||||
socket.send_to(b"peer", addr).unwrap();
|
||||
let mut b = [0; 512];
|
||||
let (n, _) = socket.recv_from(&mut b).unwrap();
|
||||
println!("{}", String::from_utf8_lossy(&b[..n]));
|
||||
return;
|
||||
}
|
||||
if a.get(1).map(String::as_str) == Some("--emit-configs") {
|
||||
let dir = PathBuf::from(&a[2]);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
for (name,q) in [("plain",""),("tls","?security=tls&sni=example.com"),("reality","?security=reality&sni=example.com&pbk=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&sid=0123&fp=chrome&flow=xtls-rprx-vision"),("ws","?type=ws&security=tls&path=%2Fsocket&host=example.com")] {
|
||||
let v=vless::parse(&format!("vless://b831381d-6324-4d53-ad4f-8cda48b30811@192.0.2.2:2443{q}")).unwrap();
|
||||
for split in [true,false] {let c=config::generate(&v,&["/usr/bin/curl".into()],split,1000);std::fs::write(dir.join(format!("{name}-{split}.json")),serde_json::to_vec_pretty(&c).unwrap()).unwrap();}
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert_eq!(a.get(1).map(String::as_str), Some("--connect"));
|
||||
let state = AppState::new(
|
||||
a[3].clone().into(),
|
||||
Some(a[2].clone().into()),
|
||||
std::env::current_exe().unwrap(),
|
||||
);
|
||||
let request = Preferences {
|
||||
// An ignored query value must not interfere with internal version parsing
|
||||
// even though that value is redacted from user-visible core logs.
|
||||
vless_url: "vless://b831381d-6324-4d53-ad4f-8cda48b30811@192.0.2.2:2443?remark=1.14".into(),
|
||||
applications: vec![a[4].clone()],
|
||||
split_tunneling: a[5] == "split",
|
||||
..Default::default()
|
||||
};
|
||||
state.connect(request).unwrap();
|
||||
let until = Instant::now() + Duration::from_secs(20);
|
||||
while Instant::now() < until {
|
||||
let status = state.status();
|
||||
if status.phase == Phase::Connected {
|
||||
println!("READY");
|
||||
std::io::stdout().flush().unwrap();
|
||||
break;
|
||||
}
|
||||
if status.phase == Phase::Error {
|
||||
eprintln!(
|
||||
"{}\n{}",
|
||||
status.error.unwrap_or_default(),
|
||||
state.logs().join("\n")
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(50));
|
||||
}
|
||||
if state.status().phase != Phase::Connected {
|
||||
state.shutdown();
|
||||
panic!("startup timeout");
|
||||
}
|
||||
let mut b = [0; 1];
|
||||
let _ = std::io::stdin().read(&mut b);
|
||||
state.shutdown();
|
||||
println!("STOPPED");
|
||||
}
|
||||
Reference in New Issue
Block a user