diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs index 8bd6892d..7234772a 100644 --- a/v2rayN/v2rayN/Handler/ConfigHandler.cs +++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs @@ -196,6 +196,16 @@ namespace v2rayN.Handler }; } + if (config.socksOutbound == null) + { + config.socksOutbound = new() + { + isEnable = false, + address = "127.0.0.1", + port = 10086 + }; + } + LazyConfig.Instance.SetConfig(config); return 0; } diff --git a/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs b/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs index 87253e54..1d8ed662 100644 --- a/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs +++ b/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs @@ -52,6 +52,8 @@ namespace v2rayN.Handler outbound(node, v2rayConfig); + socksOut(v2rayConfig); + dns(v2rayConfig); statistic(v2rayConfig); @@ -470,6 +472,7 @@ namespace v2rayN.Handler outbound.protocol = Global.trojanProtocolLite; outbound.settings.vnext = null; } + boundStreamSettings(node, outbound.streamSettings); } catch (Exception ex) @@ -698,6 +701,28 @@ namespace v2rayN.Handler return 0; } + private int socksOut(V2rayConfig v2rayConfig) + { + try + { + Outbounds4Ray outbound = v2rayConfig.outbounds[3]; + ServersItem4Ray server = outbound.settings.servers[0]; + server.address = _config.socksOutbound.address; + server.port = _config.socksOutbound.port; + + // 如果下一跳Socks功能不打开, 那么配置文件中要删除sockopt这一段 + if (! _config.socksOutbound.isEnable) + { + v2rayConfig.outbounds[0].streamSettings.sockopt = null; + } + } + catch (Exception ex) + { + Utils.SaveLog(ex.Message, ex); + } + return 0; + } + private int dns(V2rayConfig v2rayConfig) { try diff --git a/v2rayN/v2rayN/Mode/Config.cs b/v2rayN/v2rayN/Mode/Config.cs index f6639b93..6e5cb6da 100644 --- a/v2rayN/v2rayN/Mode/Config.cs +++ b/v2rayN/v2rayN/Mode/Config.cs @@ -32,6 +32,9 @@ public List globalHotkeys { get; set; } public List coreTypeItem { get; set; } + // Socks出口 + public SocksOutbound socksOutbound { get; set; } + #endregion other entities } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Mode/ConfigItems.cs b/v2rayN/v2rayN/Mode/ConfigItems.cs index 799ed299..d779d663 100644 --- a/v2rayN/v2rayN/Mode/ConfigItems.cs +++ b/v2rayN/v2rayN/Mode/ConfigItems.cs @@ -206,4 +206,13 @@ namespace v2rayN.Mode public int max_streams { get; set; } public bool padding { get; set; } } + + [Serializable] + // Socks出口 + public class SocksOutbound + { + public bool isEnable { get; set; } + public string address { get; set; } + public int port { get; set; } + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Mode/V2rayConfig.cs b/v2rayN/v2rayN/Mode/V2rayConfig.cs index 14c5dee0..0d9ee3fa 100644 --- a/v2rayN/v2rayN/Mode/V2rayConfig.cs +++ b/v2rayN/v2rayN/Mode/V2rayConfig.cs @@ -451,6 +451,9 @@ namespace v2rayN.Mode /// grpc /// public GrpcSettings4Ray grpcSettings { get; set; } + + // 设置Socks出口 + public SockoptObject sockopt { get; set; } } public class TlsSettings4Ray @@ -620,6 +623,12 @@ namespace v2rayN.Mode public int initial_windows_size { get; set; } } + // Socks出口 + public class SockoptObject + { + public string dialerProxy { get; set; } + } + public class AccountsItem4Ray { /// diff --git a/v2rayN/v2rayN/Sample/SampleClientConfig b/v2rayN/v2rayN/Sample/SampleClientConfig index a33d9bd6..d4eae82c 100644 --- a/v2rayN/v2rayN/Sample/SampleClientConfig +++ b/v2rayN/v2rayN/Sample/SampleClientConfig @@ -76,7 +76,10 @@ }] }, "streamSettings": { - "network": "tcp" + "network": "tcp", + "sockopt": { + "dialerProxy": "tunnel" + } }, "mux": { "enabled": false @@ -95,16 +98,24 @@ "type": "http" } } + }, + { + "tag": "tunnel", + "protocol": "socks", + "settings": { + "servers": [{ + "address": "127.0.0.1", + "port": 10086 + }] + } } ], "routing": { "domainStrategy": "IPIfNonMatch", - "rules": [ - { - "inboundTag": ["api"], - "outboundTag": "api", - "type": "field" - } - ] + "rules": [{ + "inboundTag": ["api"], + "outboundTag": "api", + "type": "field" + }] } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Tool/Utils.cs b/v2rayN/v2rayN/Tool/Utils.cs index d65bebae..94027d26 100644 --- a/v2rayN/v2rayN/Tool/Utils.cs +++ b/v2rayN/v2rayN/Tool/Utils.cs @@ -880,9 +880,10 @@ namespace v2rayN string location = GetExePath(); if (blFull) { - return string.Format("v2rayN - V{0} - {1}", + return string.Format("v2rayN - V{0} - {1} - {2}", FileVersionInfo.GetVersionInfo(location).FileVersion.ToString(), - File.GetLastWriteTime(location).ToString("yyyy/MM/dd")); + File.GetLastWriteTime(location).ToString("yyyy/MM/dd"), + Path.GetFileName(location)); } else { diff --git a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs index e64d3aa2..16b4c0f1 100644 --- a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs @@ -33,6 +33,11 @@ namespace v2rayN.ViewModels [Reactive] public string defUserAgent { get; set; } [Reactive] public string mux4SboxProtocol { get; set; } + // Socsk出口设置 + [Reactive] public bool socksOutboundEnable { get; set; } + [Reactive] public string socksOutboundIP { get; set; } + [Reactive] public int socksOutboundPort { get; set; } + #endregion Core #region Core KCP @@ -175,6 +180,11 @@ namespace v2rayN.ViewModels InitCoreType(); + // Socks出口 + socksOutboundEnable = _config.socksOutbound.isEnable; + socksOutboundIP = _config.socksOutbound.address; + socksOutboundPort = _config.socksOutbound.port; + SaveCmd = ReactiveCommand.Create(() => { SaveSetting(); @@ -317,6 +327,11 @@ namespace v2rayN.ViewModels //coreType SaveCoreType(); + // Socks出口 + _config.socksOutbound.isEnable = socksOutboundEnable; + _config.socksOutbound.address = socksOutboundIP; + _config.socksOutbound.port = socksOutboundPort; + if (ConfigHandler.SaveConfig(ref _config) == 0) { _noticeHandler?.Enqueue(ResUI.OperationSuccess); diff --git a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml index c2683b15..e2e65b78 100644 --- a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml @@ -939,6 +939,18 @@ Style="{StaticResource DefComboBox}" /> + + + + + + \ No newline at end of file diff --git a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs index 80f86efe..a1ff9a4f 100644 --- a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs @@ -187,6 +187,11 @@ namespace v2rayN.Views this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.Text).DisposeWith(disposables); + // Socks出口设置 + this.Bind(ViewModel, vm => vm.socksOutboundEnable, v => v.chkSocksOut.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.socksOutboundIP, v => v.txtSocksOutboundIP.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.socksOutboundPort, v => v.txtSocksOutboundPort.Text).DisposeWith(disposables); + this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); }); }