From 95f2b6bada6b9ad7db32d3724d4589c78157d31a Mon Sep 17 00:00:00 2001 From: luckfox-eng29 Date: Wed, 6 May 2026 21:30:54 +0800 Subject: [PATCH] feat(network): add proxy configuration options and environment variable handling Signed-off-by: luckfox-eng29 --- internal/network/config.go | 33 +++++++------ network.go | 25 ++++++++++ ui/src/hooks/stores.ts | 3 ++ .../network/NetworkContent.tsx | 48 +++++++++++++++++++ 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/internal/network/config.go b/internal/network/config.go index b099421..3184699 100644 --- a/internal/network/config.go +++ b/internal/network/config.go @@ -33,24 +33,27 @@ type IPv6StaticConfig struct { DNS []string `json:"dns,omitempty" validate_type:"ipv6" required:"true"` } type NetworkConfig struct { - Hostname null.String `json:"hostname,omitempty" validate_type:"hostname"` - Domain null.String `json:"domain,omitempty" validate_type:"hostname"` + Hostname null.String `json:"hostname,omitempty" validate_type:"hostname"` + Domain null.String `json:"domain,omitempty" validate_type:"hostname"` + HTTPProxy null.String `json:"http_proxy,omitempty"` + HTTPSProxy null.String `json:"https_proxy,omitempty"` + ALLProxy null.String `json:"all_proxy,omitempty"` - IPv4Mode null.String `json:"ipv4_mode,omitempty" one_of:"dhcp,static,disabled" default:"dhcp"` - IPv4RequestAddress null.String `json:"ipv4_request_address,omitempty"` - IPv4Static *IPv4StaticConfig `json:"ipv4_static,omitempty" required_if:"IPv4Mode=static"` + IPv4Mode null.String `json:"ipv4_mode,omitempty" one_of:"dhcp,static,disabled" default:"dhcp"` + IPv4RequestAddress null.String `json:"ipv4_request_address,omitempty"` + IPv4Static *IPv4StaticConfig `json:"ipv4_static,omitempty" required_if:"IPv4Mode=static"` - IPv6Mode null.String `json:"ipv6_mode,omitempty" one_of:"slaac,dhcpv6,slaac_and_dhcpv6,static,link_local,disabled" default:"slaac"` - IPv6Static *IPv6StaticConfig `json:"ipv6_static,omitempty" required_if:"IPv6Mode=static"` + IPv6Mode null.String `json:"ipv6_mode,omitempty" one_of:"slaac,dhcpv6,slaac_and_dhcpv6,static,link_local,disabled" default:"slaac"` + IPv6Static *IPv6StaticConfig `json:"ipv6_static,omitempty" required_if:"IPv6Mode=static"` - LLDPMode null.String `json:"lldp_mode,omitempty" one_of:"disabled,basic,all" default:"basic"` - LLDPTxTLVs []string `json:"lldp_tx_tlvs,omitempty" one_of:"chassis,port,system,vlan" default:"chassis,port,system,vlan"` - MDNSMode null.String `json:"mdns_mode,omitempty" one_of:"disabled,auto,ipv4_only,ipv6_only" default:"auto"` - TimeSyncMode null.String `json:"time_sync_mode,omitempty" one_of:"ntp_only,ntp_and_http,http_only,custom" default:"ntp_and_http"` - TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,ntp_fallback" default:"ntp,http"` - TimeSyncDisableFallback null.Bool `json:"time_sync_disable_fallback,omitempty" default:"false"` - TimeSyncParallel null.Int `json:"time_sync_parallel,omitempty" default:"4"` - PendingReboot null.Bool `json:"pending_reboot,omitempty" default:"false"` + LLDPMode null.String `json:"lldp_mode,omitempty" one_of:"disabled,basic,all" default:"basic"` + LLDPTxTLVs []string `json:"lldp_tx_tlvs,omitempty" one_of:"chassis,port,system,vlan" default:"chassis,port,system,vlan"` + MDNSMode null.String `json:"mdns_mode,omitempty" one_of:"disabled,auto,ipv4_only,ipv6_only" default:"auto"` + TimeSyncMode null.String `json:"time_sync_mode,omitempty" one_of:"ntp_only,ntp_and_http,http_only,custom" default:"ntp_and_http"` + TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,ntp_fallback" default:"ntp,http"` + TimeSyncDisableFallback null.Bool `json:"time_sync_disable_fallback,omitempty" default:"false"` + TimeSyncParallel null.Int `json:"time_sync_parallel,omitempty" default:"4"` + PendingReboot null.Bool `json:"pending_reboot,omitempty" default:"false"` } func (c *NetworkConfig) GetMDNSMode() *mdns.MDNSListenOptions { diff --git a/network.go b/network.go index 560ee4f..47dc0ae 100644 --- a/network.go +++ b/network.go @@ -2,6 +2,8 @@ package kvm import ( "fmt" + "os" + "strings" "kvm/internal/network" "kvm/internal/udhcpc" @@ -17,6 +19,27 @@ var ( networkState *network.NetworkInterfaceState ) +func setProxyEnvVar(key, value string) { + value = strings.TrimSpace(value) + upperKey := strings.ToUpper(key) + if value == "" { + _ = os.Unsetenv(key) + _ = os.Unsetenv(upperKey) + return + } + _ = os.Setenv(key, value) + _ = os.Setenv(upperKey, value) +} + +func applyProxyEnvironment(networkConfig *network.NetworkConfig) { + if networkConfig == nil { + return + } + setProxyEnvVar("http_proxy", networkConfig.HTTPProxy.String) + setProxyEnvVar("https_proxy", networkConfig.HTTPSProxy.String) + setProxyEnvVar("all_proxy", networkConfig.ALLProxy.String) +} + func networkStateChanged() { // do not block the main thread go waitCtrlAndRequestDisplayUpdate(true) @@ -33,6 +56,7 @@ func networkStateChanged() { func initNetwork() error { ensureConfigLoaded() + applyProxyEnvironment(config.NetworkConfig) state, err := network.NewNetworkInterfaceState(&network.NetworkInterfaceOptions{ DefaultHostname: GetDefaultHostname(), @@ -131,6 +155,7 @@ func rpcSetNetworkSettings(settings network.RpcNetworkSettings) (*network.RpcNet if err := SaveConfig(); err != nil { return nil, err } + applyProxyEnvironment(config.NetworkConfig) return &network.RpcNetworkSettings{NetworkConfig: *config.NetworkConfig}, nil } diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index 3ba48ed..7a198d9 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -938,6 +938,9 @@ export interface IPv4StaticConfig { export interface NetworkSettings { hostname: string; domain: string; + http_proxy?: string; + https_proxy?: string; + all_proxy?: string; ipv4_mode: IPv4Mode; ipv4_request_address?: string; ipv4_static?: IPv4StaticConfig; diff --git a/ui/src/layout/components_setting/network/NetworkContent.tsx b/ui/src/layout/components_setting/network/NetworkContent.tsx index 61fa08d..a89eb3c 100644 --- a/ui/src/layout/components_setting/network/NetworkContent.tsx +++ b/ui/src/layout/components_setting/network/NetworkContent.tsx @@ -39,6 +39,9 @@ dayjs.extend(relativeTime); const defaultNetworkSettings: NetworkSettings = { hostname: "", domain: "", + http_proxy: "", + https_proxy: "", + all_proxy: "", ipv4_mode: "unknown", ipv6_mode: "unknown", lldp_mode: "unknown", @@ -307,6 +310,10 @@ export default function SettingsNetwork() { setNetworkSettings({ ...networkSettings, domain: value }); }; + const handleProxyChange = (field: "http_proxy" | "https_proxy" | "all_proxy", value: string) => { + setNetworkSettings({ ...networkSettings, [field]: value }); + }; + const handleDomainOptionChange = (value: string) => { setSelectedDomainOption(value); if (value !== "custom") { @@ -537,6 +544,47 @@ export default function SettingsNetwork() { +
+ + handleProxyChange("http_proxy", e.target.value)} + className={isMobile ? "!w-full !h-[36px]" : "!w-[37%] !h-[36px]"} + /> + + + handleProxyChange("https_proxy", e.target.value)} + className={isMobile ? "!w-full !h-[36px]" : "!w-[37%] !h-[36px]"} + /> + + + handleProxyChange("all_proxy", e.target.value)} + className={isMobile ? "!w-full !h-[36px]" : "!w-[37%] !h-[36px]"} + /> + +