mirror of
https://github.com/netchx/netch.git
synced 2026-04-01 19:15:09 +08:00
PAC替换ACL
sysproxy.dll 替换为 nuget WindowsProxy
This commit is contained in:
@@ -4,8 +4,8 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Win32;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
using WindowsProxy;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace Netch.Controllers
|
||||
Global.Job.AddProcess(pPrivoxyController.Instance);
|
||||
}
|
||||
|
||||
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
||||
//if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -91,12 +91,24 @@ namespace Netch.Controllers
|
||||
if (prevEnabled)
|
||||
{
|
||||
if (prevHTTP != "")
|
||||
NativeMethods.SetGlobal(prevHTTP, prevBypass);
|
||||
{
|
||||
using var service = new ProxyService
|
||||
{
|
||||
Server = prevHTTP,
|
||||
Bypass = prevBypass
|
||||
};
|
||||
}
|
||||
if (prevPAC != "")
|
||||
NativeMethods.SetURL(prevPAC);
|
||||
{
|
||||
using var service = new ProxyService
|
||||
{
|
||||
AutoConfigUrl = prevPAC
|
||||
};
|
||||
service.Pac();
|
||||
}
|
||||
}
|
||||
else
|
||||
NativeMethods.SetDIRECT();
|
||||
new ProxyService().Direct();
|
||||
})
|
||||
};
|
||||
Task.WaitAll(tasks);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Text;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils.HttpProxyHandler;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -34,11 +35,15 @@ namespace Netch.Controllers
|
||||
|
||||
File.WriteAllText("data\\privoxy.conf", text.ToString());
|
||||
|
||||
//启动PAC服务器
|
||||
PACServerHandle.InitPACServer("127.0.0.1");
|
||||
|
||||
return StartInstanceAuto("..\\data\\privoxy.conf");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
PACServerHandle.Stop();
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,16 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public int RequestTimeout = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// PAC URL
|
||||
/// </summary>
|
||||
public string Pac_Url = "";
|
||||
|
||||
/// <summary>
|
||||
/// PAC端口
|
||||
/// </summary>
|
||||
public int Pac_Port = 2803;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 本地端口
|
||||
/// </summary>
|
||||
|
||||
@@ -28,30 +28,6 @@ namespace Netch
|
||||
[DllImport("NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")]
|
||||
public static extern bool DeleteRoute(string address, int cidr, string gateway, int index, int metric = 0);
|
||||
|
||||
/// <summary>
|
||||
/// 设置直连
|
||||
/// </summary>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetDIRECT();
|
||||
|
||||
/// <summary>
|
||||
/// 设置全局
|
||||
/// </summary>
|
||||
/// <param name="remote">地址</param>
|
||||
/// <param name="bypass">绕过</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetGlobal([MarshalAs(UnmanagedType.LPTStr)] string remote, [MarshalAs(UnmanagedType.LPTStr)] string bypass);
|
||||
|
||||
/// <summary>
|
||||
/// 设置自动代理
|
||||
/// </summary>
|
||||
/// <param name="remote">URL</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetURL([MarshalAs(UnmanagedType.LPTStr)] string remote);
|
||||
|
||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||
public static extern uint FlushDNSResolverCache();
|
||||
|
||||
|
||||
@@ -66,13 +66,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ILMerge" Version="3.0.41" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
<PackageReference Include="WindowsJobAPI" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsJobAPI" Version="5.0.1" />
|
||||
<PackageReference Include="WindowsProxy" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
99
Netch/Utils/HttpProxyHandler/HttpWebServer.cs
Normal file
99
Netch/Utils/HttpProxyHandler/HttpWebServer.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
public class HttpWebServer
|
||||
{
|
||||
private HttpListener _listener;
|
||||
private Func<HttpListenerRequest, string> _responderMethod;
|
||||
|
||||
public HttpWebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
|
||||
{
|
||||
try
|
||||
{
|
||||
_listener = new HttpListener();
|
||||
|
||||
if (!HttpListener.IsSupported)
|
||||
throw new NotSupportedException(
|
||||
"Needs Windows XP SP2, Server 2003 or later.");
|
||||
|
||||
// URI prefixes are required, for example
|
||||
// "http://localhost:8080/index/".
|
||||
if (prefixes == null || prefixes.Length == 0)
|
||||
throw new ArgumentException("prefixes");
|
||||
|
||||
// A responder method is required
|
||||
if (method == null)
|
||||
throw new ArgumentException("method");
|
||||
|
||||
foreach (string s in prefixes)
|
||||
_listener.Prefixes.Add(s);
|
||||
|
||||
_responderMethod = method;
|
||||
_listener.Start();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("HttpWebServer():" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpWebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
|
||||
: this(prefixes, method) { }
|
||||
|
||||
public void Run()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem((o) =>
|
||||
{
|
||||
Logging.Info("Webserver running...");
|
||||
try
|
||||
{
|
||||
while (_listener.IsListening)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem((c) =>
|
||||
{
|
||||
var ctx = c as HttpListenerContext;
|
||||
try
|
||||
{
|
||||
string rstr = _responderMethod(ctx.Request);
|
||||
byte[] buf = Encoding.UTF8.GetBytes(rstr);
|
||||
ctx.Response.StatusCode = 200;
|
||||
ctx.Response.ContentType = "application/x-ns-proxy-autoconfig";
|
||||
ctx.Response.ContentLength64 = buf.Length;
|
||||
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
} // suppress any exceptions
|
||||
finally
|
||||
{
|
||||
// always close the stream
|
||||
ctx.Response.OutputStream.Close();
|
||||
}
|
||||
}, _listener.GetContext());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Logging.Error(ex.Message, ex);
|
||||
Logging.Error(ex.Message);
|
||||
} // suppress any exceptions
|
||||
});
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (_listener != null)
|
||||
{
|
||||
_listener.Stop();
|
||||
_listener.Close();
|
||||
_listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
75
Netch/Utils/HttpProxyHandler/PACListHandle.cs
Normal file
75
Netch/Utils/HttpProxyHandler/PACListHandle.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供PAC功能支持
|
||||
/// </summary>
|
||||
class PACListHandle
|
||||
{
|
||||
public event EventHandler<ResultEventArgs> UpdateCompleted;
|
||||
|
||||
public class ResultEventArgs : EventArgs
|
||||
{
|
||||
public bool Success;
|
||||
|
||||
public ResultEventArgs(bool success)
|
||||
{
|
||||
Success = success;
|
||||
}
|
||||
}
|
||||
|
||||
private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt";
|
||||
|
||||
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
|
||||
|
||||
/// <summary>
|
||||
/// 更新PAC文件(GFWList)
|
||||
/// </summary>
|
||||
//public void UpdatePACFromGFWList()
|
||||
//{
|
||||
// WebClient http = new WebClient();
|
||||
// http.DownloadStringCompleted += http_DownloadStringCompleted;
|
||||
// http.DownloadStringAsync(new Uri(GFWLIST_URL));
|
||||
//}
|
||||
|
||||
//private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// File.WriteAllText(NUtils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8);
|
||||
// List<string> lines = ParseResult(e.Result);
|
||||
// string abpContent = NUtils.UnGzip(Resources.abp_js);
|
||||
// abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented));
|
||||
// File.WriteAllText(NUtils.GetPath("pac.txt"), abpContent, Encoding.UTF8);
|
||||
// if (UpdateCompleted != null) UpdateCompleted(this, new ResultEventArgs(true));
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logging.Error("http_DownloadStringCompleted():" + ex.Message);
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static List<string> ParseResult(string response)
|
||||
//{
|
||||
// byte[] bytes = Convert.FromBase64String(response);
|
||||
// string content = Encoding.ASCII.GetString(bytes);
|
||||
// List<string> valid_lines = new List<string>();
|
||||
// using (var sr = new StringReader(content))
|
||||
// {
|
||||
// foreach (var line in sr.NonWhiteSpaceLines())
|
||||
// {
|
||||
// if (line.BeginWithAny(IgnoredLineBegins))
|
||||
// continue;
|
||||
// valid_lines.Add(line);
|
||||
// }
|
||||
// }
|
||||
// return valid_lines;
|
||||
//}
|
||||
}
|
||||
}
|
||||
125
Netch/Utils/HttpProxyHandler/PACServerHandle.cs
Normal file
125
Netch/Utils/HttpProxyHandler/PACServerHandle.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using WindowsProxy;
|
||||
|
||||
namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供PAC功能支持
|
||||
/// </summary>
|
||||
class PACServerHandle
|
||||
{
|
||||
private static Hashtable httpWebServer = new Hashtable();
|
||||
private static Hashtable pacList = new Hashtable();
|
||||
|
||||
public static void InitPACServer(string address)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!pacList.ContainsKey(address))
|
||||
{
|
||||
pacList.Add(address, GetPacList(address));
|
||||
}
|
||||
|
||||
string prefixes = string.Format("http://{0}:{1}/pac/", address, Global.Settings.Pac_Port);
|
||||
|
||||
HttpWebServer ws = new HttpWebServer(SendResponse, prefixes);
|
||||
ws.Run();
|
||||
|
||||
if (!httpWebServer.ContainsKey(address) && ws != null)
|
||||
{
|
||||
httpWebServer.Add(address, ws);
|
||||
}
|
||||
Global.Settings.Pac_Url = GetPacUrl();
|
||||
|
||||
using var service = new ProxyService
|
||||
{
|
||||
AutoConfigUrl = Global.Settings.Pac_Url
|
||||
};
|
||||
service.Pac();
|
||||
|
||||
Logging.Info(service.Set(service.Query()) + "");
|
||||
Logging.Info($"Webserver InitServer OK: {Global.Settings.Pac_Url}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver InitServer " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SendResponse(HttpListenerRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] arrAddress = request.UserHostAddress.Split(':');
|
||||
string address = "127.0.0.1";
|
||||
if (arrAddress.Length > 0)
|
||||
{
|
||||
address = arrAddress[0];
|
||||
}
|
||||
return pacList[address].ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver SendResponse " + ex.Message);
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (httpWebServer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var key in httpWebServer.Keys)
|
||||
{
|
||||
Logging.Info("Webserver Stop " + key.ToString());
|
||||
((HttpWebServer)httpWebServer[key]).Stop();
|
||||
}
|
||||
httpWebServer.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver Stop " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPacList(string address)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<string> lstProxy = new List<string>();
|
||||
lstProxy.Add(string.Format("PROXY {0}:{1};", address, Global.Settings.HTTPLocalPort));
|
||||
|
||||
var proxy = string.Join("", lstProxy.ToArray());
|
||||
string strPacfile = Path.Combine(Global.NetchDir, $"bin\\pac.txt");
|
||||
|
||||
var pac = File.ReadAllText(strPacfile, Encoding.UTF8).Replace("__PROXY__", proxy);
|
||||
return pac;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return "No pac content";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取PAC地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetPacUrl()
|
||||
{
|
||||
string pacUrl = string.Format("http://127.0.0.1:{0}/pac/?t={1}", Global.Settings.Pac_Port,
|
||||
DateTime.Now.ToString("yyyyMMddHHmmssfff"));
|
||||
|
||||
return pacUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
binaries
2
binaries
Submodule binaries updated: 4525fe9c71...0b158dbc5a
Reference in New Issue
Block a user