summaryrefslogtreecommitdiff
path: root/src/xray.rs
diff options
context:
space:
mode:
authorAndrew Guschin <guschin@altlinux.org>2026-10-30 04:43:59 +0400
committerAndrew Guschin <guschin@altlinux.org>2026-10-30 04:43:59 +0400
commit7999fab25c5172207ee41e38732f4923565ff6b6 (patch)
tree0e239d6ba65d4babfc0f1007ac350f6f4f9e73d1 /src/xray.rs
parentfc3c1d51b1be9db6ba6ad286584fbc34bb305f38 (diff)
Validate controller diagnostics, reboot protection, and terminal authentication
Diffstat (limited to 'src/xray.rs')
-rw-r--r--src/xray.rs55
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;
+ }
+}