feat: Support config redir port and tproxy port

This commit is contained in:
MystiPanda 2024-03-20 23:38:47 +08:00
parent d003883de9
commit ae46332e42
7 changed files with 152 additions and 7 deletions

View File

@ -39,7 +39,10 @@ impl IClashTemp {
tun.insert("auto-detect-interface".into(), true.into()); tun.insert("auto-detect-interface".into(), true.into());
tun.insert("dns-hijack".into(), vec!["any:53"].into()); tun.insert("dns-hijack".into(), vec!["any:53"].into());
tun.insert("mtu".into(), 9000.into()); tun.insert("mtu".into(), 9000.into());
#[cfg(not(target_os = "windows"))]
map.insert("redir-port".into(), 7895.into());
#[cfg(target_os = "linux")]
map.insert("tproxy-port".into(), 7896.into());
map.insert("mixed-port".into(), 7897.into()); map.insert("mixed-port".into(), 7897.into());
map.insert("socks-port".into(), 7898.into()); map.insert("socks-port".into(), 7898.into());
map.insert("port".into(), 7899.into()); map.insert("port".into(), 7899.into());
@ -54,11 +57,18 @@ impl IClashTemp {
} }
fn guard(mut config: Mapping) -> Mapping { fn guard(mut config: Mapping) -> Mapping {
#[cfg(not(target_os = "windows"))]
let redir_port = Self::guard_redir_port(&config);
#[cfg(target_os = "linux")]
let tproxy_port = Self::guard_tproxy_port(&config);
let mixed_port = Self::guard_mixed_port(&config); let mixed_port = Self::guard_mixed_port(&config);
let socks_port = Self::guard_socks_port(&config); let socks_port = Self::guard_socks_port(&config);
let port = Self::guard_port(&config); let port = Self::guard_port(&config);
let ctrl = Self::guard_server_ctrl(&config); let ctrl = Self::guard_server_ctrl(&config);
#[cfg(not(target_os = "windows"))]
config.insert("redir-port".into(), redir_port.into());
#[cfg(target_os = "linux")]
config.insert("tproxy-port".into(), tproxy_port.into());
config.insert("mixed-port".into(), mixed_port.into()); config.insert("mixed-port".into(), mixed_port.into());
config.insert("socks-port".into(), socks_port.into()); config.insert("socks-port".into(), socks_port.into());
config.insert("port".into(), port.into()); config.insert("port".into(), port.into());
@ -110,6 +120,37 @@ impl IClashTemp {
}), }),
} }
} }
#[cfg(not(target_os = "windows"))]
pub fn guard_redir_port(config: &Mapping) -> u16 {
let mut port = config
.get("redir-port")
.and_then(|value| match value {
Value::String(val_str) => val_str.parse().ok(),
Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
_ => None,
})
.unwrap_or(7895);
if port == 0 {
port = 7895;
}
port
}
#[cfg(target_os = "linux")]
pub fn guard_tproxy_port(config: &Mapping) -> u16 {
let mut port = config
.get("tproxy-port")
.and_then(|value| match value {
Value::String(val_str) => val_str.parse().ok(),
Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
_ => None,
})
.unwrap_or(7896);
if port == 0 {
port = 7896;
}
port
}
pub fn guard_mixed_port(config: &Mapping) -> u16 { pub fn guard_mixed_port(config: &Mapping) -> u16 {
let mut port = config let mut port = config

View File

@ -126,7 +126,13 @@ pub struct IVerge {
/// 是否启用随机端口 /// 是否启用随机端口
pub enable_random_port: Option<bool>, pub enable_random_port: Option<bool>,
/// verge mixed port 用于覆盖 clash 的 mixed port /// verge 的各种 port 用于覆盖 clash 的各种 port
#[cfg(not(target_os = "windows"))]
pub verge_redir_port: Option<u16>,
#[cfg(target_os = "linux")]
pub verge_tproxy_port: Option<u16>,
pub verge_mixed_port: Option<u16>, pub verge_mixed_port: Option<u16>,
pub verge_socks_port: Option<u16>, pub verge_socks_port: Option<u16>,
@ -190,6 +196,10 @@ impl IVerge {
enable_silent_start: Some(false), enable_silent_start: Some(false),
enable_system_proxy: Some(false), enable_system_proxy: Some(false),
enable_random_port: Some(false), enable_random_port: Some(false),
#[cfg(not(target_os = "windows"))]
verge_redir_port: Some(7895),
#[cfg(target_os = "linux")]
verge_tproxy_port: Some(7896),
verge_mixed_port: Some(7897), verge_mixed_port: Some(7897),
verge_socks_port: Some(7898), verge_socks_port: Some(7898),
verge_port: Some(7899), verge_port: Some(7899),
@ -239,6 +249,10 @@ impl IVerge {
patch!(enable_auto_launch); patch!(enable_auto_launch);
patch!(enable_silent_start); patch!(enable_silent_start);
patch!(enable_random_port); patch!(enable_random_port);
#[cfg(not(target_os = "windows"))]
patch!(verge_redir_port);
#[cfg(target_os = "linux")]
patch!(verge_tproxy_port);
patch!(verge_mixed_port); patch!(verge_mixed_port);
patch!(verge_socks_port); patch!(verge_socks_port);
patch!(verge_port); patch!(verge_port);

View File

@ -1,8 +1,10 @@
use serde_yaml::{Mapping, Value}; use serde_yaml::{Mapping, Value};
use std::collections::HashSet; use std::collections::HashSet;
pub const HANDLE_FIELDS: [&str; 9] = [ pub const HANDLE_FIELDS: [&str; 11] = [
"mode", "mode",
"redir-port",
"tproxy-port",
"mixed-port", "mixed-port",
"socks-port", "socks-port",
"port", "port",

View File

@ -107,6 +107,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
Config::clash().draft().patch_config(patch.clone()); Config::clash().draft().patch_config(patch.clone());
match { match {
let redir_port = patch.get("redir-port");
let tproxy_port = patch.get("tproxy-port");
let mixed_port = patch.get("mixed-port"); let mixed_port = patch.get("mixed-port");
let socks_port = patch.get("socks-port"); let socks_port = patch.get("socks-port");
let port = patch.get("port"); let port = patch.get("port");
@ -129,7 +131,9 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
}; };
// 激活订阅 // 激活订阅
if mixed_port.is_some() if redir_port.is_some()
|| tproxy_port.is_some()
|| mixed_port.is_some()
|| socks_port.is_some() || socks_port.is_some()
|| port.is_some() || port.is_some()
|| patch.get("secret").is_some() || patch.get("secret").is_some()

View File

@ -5,6 +5,8 @@ import { List, ListItem, ListItemText, TextField } from "@mui/material";
import { useClashInfo } from "@/hooks/use-clash"; import { useClashInfo } from "@/hooks/use-clash";
import { BaseDialog, DialogRef, Notice } from "@/components/base"; import { BaseDialog, DialogRef, Notice } from "@/components/base";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import getSystem from "@/utils/get-system";
const OS = getSystem();
export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => { export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -13,6 +15,12 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
const { verge, patchVerge } = useVerge(); const { verge, patchVerge } = useVerge();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [redirPort, setRedirPort] = useState(
verge?.verge_redir_port ?? clashInfo?.redir_port ?? 7895
);
const [tproxyPort, setTproxyPort] = useState(
verge?.verge_tproxy_port ?? clashInfo?.tproxy_port ?? 7896
);
const [mixedPort, setMixedPort] = useState( const [mixedPort, setMixedPort] = useState(
verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897 verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897
); );
@ -25,6 +33,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
open: () => { open: () => {
if (verge?.verge_redir_port) setRedirPort(verge?.verge_redir_port);
if (verge?.verge_tproxy_port) setTproxyPort(verge?.verge_tproxy_port);
if (verge?.verge_mixed_port) setMixedPort(verge?.verge_mixed_port); if (verge?.verge_mixed_port) setMixedPort(verge?.verge_mixed_port);
if (verge?.verge_socks_port) setSocksPort(verge?.verge_socks_port); if (verge?.verge_socks_port) setSocksPort(verge?.verge_socks_port);
if (verge?.verge_port) setPort(verge?.verge_port); if (verge?.verge_port) setPort(verge?.verge_port);
@ -35,6 +45,8 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
const onSave = useLockFn(async () => { const onSave = useLockFn(async () => {
if ( if (
redirPort === verge?.verge_redir_port &&
tproxyPort === verge?.verge_tproxy_port &&
mixedPort === verge?.verge_mixed_port && mixedPort === verge?.verge_mixed_port &&
socksPort === verge?.verge_socks_port && socksPort === verge?.verge_socks_port &&
port === verge?.verge_port port === verge?.verge_port
@ -42,11 +54,22 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
setOpen(false); setOpen(false);
return; return;
} }
if (mixedPort === socksPort || mixedPort === port || socksPort === port) {
if (
new Set([redirPort, tproxyPort, mixedPort, socksPort, port]).size !== 5
) {
Notice.error("Port conflict!", 4000); Notice.error("Port conflict!", 4000);
return; return;
} }
try { try {
if (OS !== "windows") {
await patchInfo({ "redir-port": redirPort });
await patchVerge({ verge_redir_port: redirPort });
}
if (OS === "linux") {
await patchInfo({ "tproxy-port": tproxyPort });
await patchVerge({ verge_tproxy_port: tproxyPort });
}
await patchInfo({ "mixed-port": mixedPort }); await patchInfo({ "mixed-port": mixedPort });
await patchInfo({ "socks-port": socksPort }); await patchInfo({ "socks-port": socksPort });
await patchInfo({ port }); await patchInfo({ port });
@ -72,6 +95,35 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
onOk={onSave} onOk={onSave}
> >
<List> <List>
{OS !== "windows" && (
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Redir Port" />
<TextField
size="small"
autoComplete="off"
sx={{ width: 135 }}
value={redirPort}
onChange={(e) =>
setRedirPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
}
/>
</ListItem>
)}
{OS === "linux" && (
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Tproxy Port" />
<TextField
size="small"
autoComplete="off"
sx={{ width: 135 }}
value={tproxyPort}
onChange={(e) =>
setTproxyPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
}
/>
</ListItem>
)}
<ListItem sx={{ padding: "5px 2px" }}> <ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Mixed Port" /> <ListItemText primary="Mixed Port" />
<TextField <TextField

View File

@ -49,11 +49,19 @@ export const useClashInfo = () => {
patch: Partial< patch: Partial<
Pick< Pick<
IConfigData, IConfigData,
"port" | "socks-port" | "mixed-port" | "external-controller" | "secret" | "port"
| "socks-port"
| "mixed-port"
| "redir-port"
| "tproxy-port"
| "external-controller"
| "secret"
> >
> >
) => { ) => {
const hasInfo = const hasInfo =
patch["redir-port"] != null ||
patch["tproxy-port"] != null ||
patch["mixed-port"] != null || patch["mixed-port"] != null ||
patch["socks-port"] != null || patch["socks-port"] != null ||
patch["port"] != null || patch["port"] != null ||
@ -62,6 +70,26 @@ export const useClashInfo = () => {
if (!hasInfo) return; if (!hasInfo) return;
if (patch["redir-port"]) {
const port = patch["redir-port"];
if (port < 1000) {
throw new Error("The port should not < 1000");
}
if (port > 65536) {
throw new Error("The port should not > 65536");
}
}
if (patch["tproxy-port"]) {
const port = patch["tproxy-port"];
if (port < 1000) {
throw new Error("The port should not < 1000");
}
if (port > 65536) {
throw new Error("The port should not > 65536");
}
}
if (patch["mixed-port"]) { if (patch["mixed-port"]) {
const port = patch["mixed-port"]; const port = patch["mixed-port"];
if (port < 1000) { if (port < 1000) {

View File

@ -142,6 +142,8 @@ interface IClashInfo {
// status: string; // status: string;
mixed_port?: number; // clash mixed port mixed_port?: number; // clash mixed port
socks_port?: number; // clash socks port socks_port?: number; // clash socks port
redir_port?: number; // clash redir port
tproxy_port?: number; // clash tproxy port
port?: number; // clash http port port?: number; // clash http port
server?: string; // external-controller server?: string; // external-controller
secret?: string; secret?: string;
@ -214,6 +216,8 @@ interface IVergeConfig {
enable_random_port?: boolean; enable_random_port?: boolean;
verge_mixed_port?: number; verge_mixed_port?: number;
verge_socks_port?: number; verge_socks_port?: number;
verge_redir_port?: number;
verge_tproxy_port?: number;
verge_port?: number; verge_port?: number;
enable_proxy_guard?: boolean; enable_proxy_guard?: boolean;
proxy_guard_duration?: number; proxy_guard_duration?: number;