libsubconverter/parser/explodes/
wireguard.rs1use crate::{utils::url_decode, Proxy};
2use regex::Regex;
3use std::collections::HashMap;
4use url::Url;
5
6pub fn explode_wireguard(wireguard: &str, node: &mut Proxy) -> bool {
8 if !wireguard.starts_with("wireguard://") {
10 return false;
11 }
12
13 let url = match Url::parse(wireguard) {
15 Ok(url) => url,
16 Err(_) => return false,
17 };
18
19 let mut params = HashMap::new();
21 for (key, value) in url.query_pairs() {
22 params.insert(key.to_string(), url_decode(&value));
23 }
24
25 let private_key = match params.get("privateKey") {
27 Some(key) => key,
28 None => return false,
29 };
30
31 let public_key = match params.get("publicKey") {
32 Some(key) => key,
33 None => return false,
34 };
35
36 let host = match url.host_str() {
38 Some(host) => host,
39 None => return false,
40 };
41 let port = url.port().unwrap_or(51820);
42
43 let preshared_key = params.get("presharedKey").map(|s| s.as_str()).unwrap_or("");
45 let self_ip = params
46 .get("selfIP")
47 .map(|s| s.as_str())
48 .unwrap_or("10.0.0.2");
49 let self_ipv6 = params.get("selfIPv6").map(|s| s.as_str()).unwrap_or("");
50 let mtu = params
51 .get("mtu")
52 .map(|s| s.parse::<u16>().unwrap_or(1420))
53 .unwrap_or(1420);
54 let keep_alive = params
55 .get("keepAlive")
56 .map(|s| s.parse::<u16>().unwrap_or(25))
57 .unwrap_or(25);
58
59 let dns_str = params.get("dns").map(|s| s.as_str()).unwrap_or("");
61 let dns_servers: Vec<String> = if dns_str.is_empty() {
62 vec!["1.1.1.1".to_string()]
63 } else {
64 dns_str.split(',').map(|s| s.trim().to_string()).collect()
65 };
66
67 let remark = url_decode(url.fragment().unwrap_or(""));
69 let formatted_remark = if remark.is_empty() {
70 format!("{} ({})", host, port)
71 } else {
72 remark.to_string()
73 };
74
75 *node = Proxy::wireguard_construct(
77 "WireGuard".to_string(),
78 formatted_remark,
79 host.to_string(),
80 port,
81 self_ip.to_string(),
82 self_ipv6.to_string(),
83 private_key.to_string(),
84 public_key.to_string(),
85 preshared_key.to_string(),
86 dns_servers,
87 Some(mtu),
88 Some(keep_alive),
89 "https://www.gstatic.com/generate_204".to_string(),
90 "".to_string(),
91 None,
92 None,
93 );
94 parse_peers(wireguard, node);
95
96 true
97}
98
99pub fn parse_peers(data: &str, node: &mut Proxy) -> bool {
101 let peer_regex = Regex::new(r"\((.*?)\)").unwrap();
103 let peers: Vec<&str> = peer_regex
104 .captures_iter(data)
105 .filter_map(|cap| cap.get(1))
106 .map(|m| m.as_str())
107 .collect();
108
109 if peers.is_empty() {
110 return false;
111 }
112
113 let peer = peers[0];
115
116 let pair_regex = Regex::new(r#"([a-z-]+) ?= ?([^" ),]+|".*?"),? ?"#).unwrap();
118 let pairs: Vec<(String, String)> = pair_regex
119 .captures_iter(peer)
120 .filter_map(|cap| {
121 if let (Some(key), Some(val)) = (cap.get(1), cap.get(2)) {
122 Some((key.as_str().to_string(), val.as_str().to_string()))
123 } else {
124 None
125 }
126 })
127 .collect();
128
129 if pairs.is_empty() {
130 return false;
131 }
132
133 for (key, val) in pairs {
135 match key.as_str() {
136 "public-key" => {
137 node.public_key = Some(val);
138 }
139 "endpoint" => {
140 if let Some(idx) = val.rfind(':') {
141 node.hostname = val[..idx].to_string();
142 if let Ok(port) = val[idx + 1..].parse::<u16>() {
143 node.port = port;
144 }
145 }
146 }
147 "client-id" => {
148 node.client_id = Some(val);
149 }
150 "allowed-ips" => {
151 node.allowed_ips = val.trim_matches('"').to_string();
152 }
153 _ => {}
154 }
155 }
156
157 true
158}