PAC替换ACL

sysproxy.dll 替换为 nuget WindowsProxy
This commit is contained in:
AmazingDM
2020-12-24 22:57:52 +08:00
parent 669ca4902f
commit ad3053298a
9 changed files with 335 additions and 32 deletions

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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();

View File

@@ -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>

View 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;
}
}
}
}

View 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;
//}
}
}

View 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;
}
}
}