Skip to content

Commit

Permalink
When set the linux system proxy, use shell scripts instead of command…
Browse files Browse the repository at this point in the history
… lines
  • Loading branch information
2dust committed Feb 24, 2025
1 parent 72ff947 commit 29e8df7
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 196 deletions.
6 changes: 0 additions & 6 deletions v2rayN/ServiceLib/Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -885,12 +885,6 @@ public static bool IsAdministrator()
: Environment.GetEnvironmentVariable("HOME");
}

public static async Task<string?> GetListNetworkServices()
{
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
return await GetCliWrapOutput(Global.LinuxBash, arg);
}

#endregion Platform
}
}
1 change: 1 addition & 0 deletions v2rayN/ServiceLib/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class Global
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
public const string PacFileName = NamespaceSample + "pac";
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";

public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp";
Expand Down
199 changes: 15 additions & 184 deletions v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs
Original file line number Diff line number Diff line change
@@ -1,202 +1,33 @@
namespace ServiceLib.Handler.SysProxy
namespace ServiceLib.Handler.SysProxy
{
public class ProxySettingLinux
{
private static readonly string _proxySetFileName = $"{Global.ProxySetLinuxShellFileName.Replace(Global.NamespaceSample, "")}.sh";

public static async Task SetProxy(string host, int port, string exceptions)
{
var lstCmd = GetSetCmds(host, port, exceptions);

await ExecCmd(lstCmd);
List<string> args = ["manual", host, port.ToString(), exceptions];
await ExecCmd(args);
}

public static async Task UnsetProxy()
{
var lstCmd = GetUnsetCmds();

await ExecCmd(lstCmd);
}

private static async Task ExecCmd(List<CmdItem> lstCmd)
{
foreach (var cmd in lstCmd)
{
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
{
continue;
}
await Task.Delay(10);
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
}
}

private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
{
var isKde = IsKde(out var configDir);
List<string> lstType = ["", "http", "https", "socks", "ftp"];
List<CmdItem> lstCmd = [];

//GNOME
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
}

if (isKde)
{
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
}

// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
}
return lstCmd;
List<string> args = ["none"];
await ExecCmd(args);
}

private static List<CmdItem> GetUnsetCmds()
private static async Task ExecCmd(List<string> args)
{
var isKde = IsKde(out var configDir);
List<CmdItem> lstCmd = [];

//GNOME
lstCmd.Add(new CmdItem()
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
if (!File.Exists(fileName))
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
});
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
await File.AppendAllTextAsync(fileName, contents);

if (isKde)
{
lstCmd.Add(new CmdItem()
{
Cmd = GetKdeVersion(),
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
});

// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
await Utils.SetLinuxChmod(fileName);
}
return lstCmd;
}

private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
{
List<CmdItem> lstCmd = [];
var cmd = GetKdeVersion();

if (type.IsNullOrEmpty())
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
});
}
else
{
var type2 = type.Equals("https") ? "http" : type;
lstCmd.Add(new CmdItem()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
});
}

return lstCmd;
}

private static List<CmdItem> GetSetCmd4Gnome(string type, string host, int port)
{
List<CmdItem> lstCmd = [];

if (type.IsNullOrEmpty())
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
});
}
else
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy.{type}", "host", host]
});

lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy.{type}", "port", $"{port}"]
});
}

return lstCmd;
}

private static bool IsKde(out string configDir)
{
configDir = "/home";
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
var desktop2 = Environment.GetEnvironmentVariable("XDG_SESSION_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop, "plasma", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "plasma", StringComparison.OrdinalIgnoreCase);
if (isKde)
{
var homeDir = Environment.GetEnvironmentVariable("HOME");
if (homeDir != null)
{
configDir = Path.Combine(homeDir, ".config");
}
}

return isKde;
}

private static string GetKdeVersion()
{
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
return ver switch
{
"6" => "kwriteconfig6",
_ => "kwriteconfig5"
};
await Utils.GetCliWrapOutput(fileName, args);
}
}
}
}
118 changes: 118 additions & 0 deletions v2rayN/ServiceLib/Sample/proxy_set_linux_sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash

# Function to set proxy for GNOME
set_gnome_proxy() {
local MODE=$1
local PROXY_IP=$2
local PROXY_PORT=$3
local IGNORE_HOSTS=$4

# Set the proxy mode
gsettings set org.gnome.system.proxy mode "$MODE"

if [ "$MODE" == "manual" ]; then
# List of protocols
local PROTOCOLS=("http" "https" "ftp" "socks")

# Loop through protocols to set the proxy
for PROTOCOL in "${PROTOCOLS[@]}"; do
gsettings set org.gnome.system.proxy.$PROTOCOL host "$PROXY_IP"
gsettings set org.gnome.system.proxy.$PROTOCOL port "$PROXY_PORT"
done

# Set ignored hosts
gsettings set org.gnome.system.proxy ignore-hosts "['$IGNORE_HOSTS']"

echo "GNOME: Manual proxy settings applied."
echo "Proxy IP: $PROXY_IP"
echo "Proxy Port: $PROXY_PORT"
echo "Ignored Hosts: $IGNORE_HOSTS"
elif [ "$MODE" == "none" ]; then
echo "GNOME: Proxy disabled."
else
echo "GNOME: Invalid mode. Use 'none' or 'manual'."
exit 1
fi
}

# Function to set proxy for KDE
set_kde_proxy() {
local MODE=$1
local PROXY_IP=$2
local PROXY_PORT=$3
local IGNORE_HOSTS=$4

# Determine the correct kwriteconfig command based on KDE_SESSION_VERSION
if [ "$KDE_SESSION_VERSION" == "6" ]; then
KWRITECONFIG="kwriteconfig6"
else
KWRITECONFIG="kwriteconfig5"
fi

# KDE uses kwriteconfig to modify proxy settings
if [ "$MODE" == "manual" ]; then
# Set proxy for all protocols
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ProxyType 1
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key httpProxy "http://$PROXY_IP:$PROXY_PORT"
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key httpsProxy "http://$PROXY_IP:$PROXY_PORT"
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ftpProxy "http://$PROXY_IP:$PROXY_PORT"
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key socksProxy "http://$PROXY_IP:$PROXY_PORT"

# Set ignored hosts
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key NoProxyFor "$IGNORE_HOSTS"

echo "KDE: Manual proxy settings applied."
echo "Proxy IP: $PROXY_IP"
echo "Proxy Port: $PROXY_PORT"
echo "Ignored Hosts: $IGNORE_HOSTS"
elif [ "$MODE" == "none" ]; then
# Disable proxy
$KWRITECONFIG --file kioslaverc --group "Proxy Settings" --key ProxyType 0
echo "KDE: Proxy disabled."
else
echo "KDE: Invalid mode. Use 'none' or 'manual'."
exit 1
fi

# Apply changes by restarting KDE's network settings
dbus-send --type=signal /KIO/Scheduler org.kde.KIO.Scheduler.reparseSlaveConfiguration string:""
}

# Detect the current desktop environment
detect_desktop_environment() {
if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ] || [ "$XDG_CURRENT_DESKTOP" == "ubuntu:GNOME" ] || [ "$XDG_SESSION_DESKTOP" == "GNOME" ] || [ "$XDG_SESSION_DESKTOP" == "ubuntu:GNOME" ]; then
echo "gnome"
elif [ "$XDG_CURRENT_DESKTOP" == "KDE" ] || [ "$XDG_CURRENT_DESKTOP" == "plasma" ] || [ "$XDG_SESSION_DESKTOP" == "KDE" ] || [ "$XDG_SESSION_DESKTOP" == "plasma" ]; then
echo "kde"
else
echo "unsupported"
fi
}

# Main script logic
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <mode> [proxy_ip proxy_port ignore_hosts]"
echo " mode: 'none' or 'manual'"
echo " If mode is 'manual', provide proxy IP, port, and ignore hosts."
exit 1
fi

# Get the mode
MODE=$1
PROXY_IP=$2
PROXY_PORT=$3
IGNORE_HOSTS=$4

# Detect desktop environment
DE=$(detect_desktop_environment)

# Apply settings based on the desktop environment
if [ "$DE" == "gnome" ]; then
set_gnome_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
elif [ "$DE" == "kde" ]; then
set_gnome_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
set_kde_proxy "$MODE" "$PROXY_IP" "$PROXY_PORT" "$IGNORE_HOSTS"
else
echo "Unsupported desktop environment: $DE"
exit 1
fi
12 changes: 6 additions & 6 deletions v2rayN/ServiceLib/Sample/proxy_set_osx_sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

# Function to set proxy
set_proxy() {
IP=$1
PORT=$2
PROXY_IP=$1
PROXY_PORT=$2

shift 2
BYPASS_DOMAINS=("$@")
Expand All @@ -19,17 +19,17 @@ set_proxy() {
echo "$SERVICES" | while read -r SERVICE; do
echo "Setting proxy for network service '$SERVICE'..."
# Set HTTP proxy
networksetup -setwebproxy "$SERVICE" "$IP" "$PORT"
networksetup -setwebproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"

# Set HTTPS proxy
networksetup -setsecurewebproxy "$SERVICE" "$IP" "$PORT"
networksetup -setsecurewebproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"

# Set SOCKS proxy
networksetup -setsocksfirewallproxy "$SERVICE" "$IP" "$PORT"
networksetup -setsocksfirewallproxy "$SERVICE" "$PROXY_IP" "$PROXY_PORT"

# Set bypass domains
networksetup -setproxybypassdomains "$SERVICE" "${BYPASS_DOMAINS[@]}"
echo "Proxy for network service '$SERVICE' has been set to $IP:$PORT"
echo "Proxy for network service '$SERVICE' has been set to $PROXY_IP:$PROXY_PORT"
done
echo "Proxy settings for all network services are complete!"
}
Expand Down
Loading

0 comments on commit 29e8df7

Please sign in to comment.