diff options
| author | Andrew Guschin <guschin@altlinux.org> | 2026-10-30 04:43:59 +0400 |
|---|---|---|
| committer | Andrew Guschin <guschin@altlinux.org> | 2026-10-30 04:43:59 +0400 |
| commit | 7999fab25c5172207ee41e38732f4923565ff6b6 (patch) | |
| tree | 0e239d6ba65d4babfc0f1007ac350f6f4f9e73d1 /src/xray.rs | |
| parent | fc3c1d51b1be9db6ba6ad286584fbc34bb305f38 (diff) | |
Validate controller diagnostics, reboot protection, and terminal authentication
Diffstat (limited to 'src/xray.rs')
| -rw-r--r-- | src/xray.rs | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/src/xray.rs b/src/xray.rs index c57147c..8e2135d 100644 --- a/src/xray.rs +++ b/src/xray.rs @@ -84,6 +84,27 @@ pub fn configuration(connection: &Trojan, tun: bool) -> Value { json!({"log":{"loglevel":"none"},"inbounds":inbounds,"outbounds":[{"tag":"proxy","protocol":"trojan","settings":{"servers":[{"address":connection.host,"port":connection.port,"password":connection.password}]},"streamSettings":{"network":"tcp","security":"tls","tlsSettings":tls}}]}) } +/// Listener policy is supplied by the trusted runtime, never by a subscription. +pub struct ProbeListener<'a> { + pub port: u16, + pub password: &'a str, + pub certificate: &'a str, + pub private_key: &'a str, +} + +pub fn probe_configuration(connection: &Trojan, listener: &ProbeListener<'_>) -> Value { + let mut configuration = configuration(connection, false); + configuration["inbounds"] = json!([{ + "tag":"probe", "listen":"127.0.0.1", "port":listener.port, "protocol":"http", + "settings":{"accounts":[{"user":"roentgen","pass":listener.password}]}, + "streamSettings":{"network":"tcp","security":"tls","tlsSettings":{"certificates":[{ + "certificate":listener.certificate.lines().collect::<Vec<_>>(), + "key":listener.private_key.lines().collect::<Vec<_>>() + }]}} + }]); + configuration +} + pub fn write_config(path: &Path, value: &Value) -> Result<()> { let (_, gid) = identity()?; fs::create_dir_all(RUNTIME_DIR)?; @@ -117,8 +138,8 @@ pub async fn systemctl(args: &[&str]) -> Result<()> { pub struct Probe { unit: String, path: std::path::PathBuf, - pub proxy: String, - pub certificate: String, + proxy: String, + certificate: String, active: bool, } impl Probe { @@ -132,14 +153,15 @@ impl Probe { let certified = rcgen::generate_simple_self_signed(vec!["127.0.0.1".into()])?; let certificate = certified.cert.pem(); let key = certified.key_pair.serialize_pem(); - let mut configuration = configuration(connection, false); - configuration["inbounds"] = json!([{ - "tag":"probe", "listen":"127.0.0.1", "port":port, "protocol":"http", - "settings":{"accounts":[{"user":"roentgen","pass":token}]}, - "streamSettings":{"network":"tcp","security":"tls","tlsSettings":{"certificates":[{ - "certificate":certificate.lines().collect::<Vec<_>>(), "key":key.lines().collect::<Vec<_>>() - }]}} - }]); + let configuration = probe_configuration( + connection, + &ProbeListener { + port, + password: &token, + certificate: &certificate, + private_key: &key, + }, + ); write_config(&path, &configuration)?; drop(listener); let runtime_limit = format!("RuntimeMaxSec={}", duration.saturating_add(10)); @@ -211,3 +233,16 @@ impl Drop for Probe { // systemd RuntimeMaxSec also bounds the process after controller death. } } + +#[async_trait::async_trait] +impl crate::runtime::ProbeSession for Probe { + fn connection(&self) -> crate::runtime::ProbeConnection<'_> { + crate::runtime::ProbeConnection { + proxy_url: &self.proxy, + certificate: &self.certificate, + } + } + async fn stop(self: Box<Self>) { + Probe::stop(*self).await; + } +} |