v2rayN
v2rayN copied to clipboard
[Code Bug]: ProxySetting.SetProxy() & SetIEProxy()
https://github.com/2dust/v2rayN/blob/dafc83aa534ff71022f5faf6b116f6cd2b3ac6f0/v2rayN/v2rayN/Handler/SysProxyHandle.cs#L82
Where both functions are called:
ProxySetting.SetProxy(strProxy, strExceptions, 2);
SetIEProxy(true, strProxy, strExceptions);
ProxySetting.SetProxy()
internally calls the InternetSetOption()
API to change system proxy.
SetIEProxy()
internally calls sysproxy.exe
, which internally calls the InternetSetOption()
API to change system proxy.
They are the same thing.
Calling sysproxy.exe
seems to trigger various problems, thus ProxySetting.SetProxy()
is preferred.
https://github.com/2dust/v2rayN/issues?q=sysproxy.exe+
===================
Update regarding https://github.com/2dust/v2rayN/issues/2233 :
Currently ProxySetting.SetProxy()
doesn't quite work, because its call to InternetSetOption()
is not proper.
- From https://github.com/Noisyfox/sysproxy/blob/54133d2fff6f0dabffa3eaa971d7fdb7a6e1b48e/sysproxy/main.c#L85 , we can see that
InternetSetOption()
is called 3 times, with different flags. - From https://github.com/Noisyfox/sysproxy/blob/54133d2fff6f0dabffa3eaa971d7fdb7a6e1b48e/sysproxy/main.c#L116 , we can see that the change is applied to all RAS entries, besides the default connection.
Please help fix this bug
Please help fix this bug
I'll try, but feel free to take it.
@2dust æè¿æ空ç 究äºä¸ä¸è¿ä¸ªé®é¢ï¼åç°å¨sysproxyéé¢è°ç¨äºRasEnumEntriesæ举ææç½å¡ï¼ç¶å对æ¯ä¸ªç½å¡è°ç¨InternetSetOptionã åè代ç ï¼https://github.com/shadowsocks/sysproxy/blob/master/sysproxy/main.c#L119
èè¿ä¸ªv2rayN C#代ç 没è°ç¨RasEnumEntriesï¼ pszConnection 没æèµå¼çç»ææ¯nullï¼å³LAN connectionï¼èPPPoEæ¯WAN connectioné ææ æ³å·¥ä½ãåèï¼https://learn.microsoft.com/en-us/windows/win32/wininet/setting-and-retrieving-internet-options
æ¤å¤ç®åC#代ç é没æè°ç¨INTERNET_OPTION_PROXY_SETTINGS_CHANGEDåINTERNET_OPTION_REFRESHéç¥ç³»ç»å ¶ä»åºç¨é ç½®æ´æ°äºã
ä¿®å¤åæ³å°±æ¯ç §çsysproxyéå»å®ç°ãä¸è¿æè¿é没æPPPoEçç½ç»ï¼æ æ³è°è¯éªè¯ãä¸é¢æ¯èä¾ä»£ç ï¼
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
public class ProxySettings
{
// Define P/Invoke signatures
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
[DllImport("Rasapi32.dll", CharSet = CharSet.Auto)]
private static extern uint RasEnumEntries(string reserved, string lpszPhonebook, [In, Out] RASENTRYNAME[] lprasentryname, ref int lpcb, ref int lpcEntries);
// Define necessary constants and structs...
private const int RAS_MaxEntryName = 256;
private const int RAS_MaxDeviceType = 16;
private const int RAS_MaxDeviceName = 128;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASENTRYNAME
{
public int dwSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)]
public string szEntryName;
// Other fields omitted...
}
// çç¥å£°æINTERNET_PER_CONN_OPTION, INTERNET_PER_CONN_OPTION_LIST, and other structs/constants...
public static void SetSocks5Proxy(string proxy)
{
foreach (var connection in EnumerateRasEntries())
{
SetProxy(connection, PROXY_TYPE_PROXY, proxy);
}
}
public static void SetDirectConnection()
{
foreach (var connection in EnumerateRasEntries())
{
SetProxy(connection, PROXY_TYPE_DIRECT, null);
}
}
// æ举ææè¿æ¥
private static IEnumerable<string> EnumerateRasEntries()
{
var entries = new List<string>();
int bufSize = Marshal.SizeOf(typeof(RASENTRYNAME));
RASENTRYNAME[] rasEntryNames = new RASENTRYNAME[1];
rasEntryNames[0].dwSize = bufSize;
int size = bufSize;
int numEntries = 0;
uint result = RasEnumEntries(null, null, rasEntryNames, ref size, ref numEntries);
if (result != 0)
{
throw new ApplicationException("RasEnumEntries failed.");
}
for (int i = 0; i < numEntries; i++)
{
entries.Add(rasEntryNames[i].szEntryName);
}
return entries;
}
//设置代çæå¡å¨ï¼connectionNameæ¯ä¸é¢æ举çè¿æ¥å称ï¼proxyTypeæ¯ä»£çç±»åï¼proxyæ¯ä»£çæå¡å¨å°å
private static void SetProxy(string connectionName, int proxyType, string proxy)
{
INTERNET_PER_CONN_OPTION[] options = new INTERNET_PER_CONN_OPTION[2];
options[0].Option = INTERNET_PER_CONN_FLAGS;
options[0].Value.IntValue = proxyType;
options[1].Option = INTERNET_PER_CONN_PROXY_SERVER;
if (proxyType == PROXY_TYPE_PROXY)
{
options[1].Value.StringPtrValue = Marshal.StringToHGlobalAuto(proxy);
}
else
{
options[1].Value.StringPtrValue = IntPtr.Zero;
}
INTERNET_PER_CONN_OPTION_LIST optionList = new INTERNET_PER_CONN_OPTION_LIST();
int listSize = Marshal.SizeOf(optionList);
optionList.Size = listSize;
optionList.Connection = Marshal.StringToHGlobalAuto(connectionName); // Use the connection name
optionList.OptionCount = options.Length;
optionList.OptionError = 0;
int optionSize = Marshal.SizeOf(options[0]);
IntPtr optionPtr = Marshal.AllocCoTaskMem(optionSize * options.Length);
for (int i = 0; i < options.Length; ++i)
{
IntPtr opt = new IntPtr(optionPtr.ToInt64() + (i * optionSize));
Marshal.StructureToPtr(options[i], opt, false);
}
optionList.Options = optionPtr;
// Apply the new settings
Marshal.StructureToPtr(optionList, optionPtr, false);
bool result = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PER_CONNECTION_OPTION, optionPtr, listSize);
// Notify the system that the registry settings have been changed and cause them to be refreshed
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
if (!result)
{
throw new ApplicationException("Setting proxy failed.");
}
// Free the allocated memory
Marshal.FreeCoTaskMem(optionPtr);
Marshal.FreeHGlobal(optionList.Connection);
if (proxyType == PROXY_TYPE_PROXY)
{
Marshal.FreeHGlobal(options[1].Value.StringPtrValue);
}
}
}
// Usage example
ProxySettings.SetSocks5Proxy("127.0.0.1:1080"); // Set SOCKS5 proxy
ProxySettings.SetDirectConnection(); // Set direct connection (no proxy)