diff --git a/Netch/Controllers/HTTPController.cs b/Netch/Controllers/HTTPController.cs
index c38a2edf..a4c774fc 100644
--- a/Netch/Controllers/HTTPController.cs
+++ b/Netch/Controllers/HTTPController.cs
@@ -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);
diff --git a/Netch/Controllers/PrivoxyController.cs b/Netch/Controllers/PrivoxyController.cs
index ffe4a3d2..8b2de3b4 100644
--- a/Netch/Controllers/PrivoxyController.cs
+++ b/Netch/Controllers/PrivoxyController.cs
@@ -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();
}
}
diff --git a/Netch/Models/Setting.cs b/Netch/Models/Setting.cs
index 09751d11..0ba2c1a2 100644
--- a/Netch/Models/Setting.cs
+++ b/Netch/Models/Setting.cs
@@ -155,6 +155,16 @@ namespace Netch.Models
///
public int RequestTimeout = 10000;
+ ///
+ /// PAC URL
+ ///
+ public string Pac_Url = "";
+
+ ///
+ /// PAC端口
+ ///
+ public int Pac_Port = 2803;
+
///
/// HTTP 本地端口
///
diff --git a/Netch/NativeMethods.cs b/Netch/NativeMethods.cs
index 337fdca6..510509f1 100644
--- a/Netch/NativeMethods.cs
+++ b/Netch/NativeMethods.cs
@@ -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);
- ///
- /// 设置直连
- ///
- /// 是否成功
- [DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
- public static extern bool SetDIRECT();
-
- ///
- /// 设置全局
- ///
- /// 地址
- /// 绕过
- /// 是否成功
- [DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
- public static extern bool SetGlobal([MarshalAs(UnmanagedType.LPTStr)] string remote, [MarshalAs(UnmanagedType.LPTStr)] string bypass);
-
- ///
- /// 设置自动代理
- ///
- /// URL
- /// 是否成功
- [DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
- public static extern bool SetURL([MarshalAs(UnmanagedType.LPTStr)] string remote);
-
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint FlushDNSResolverCache();
diff --git a/Netch/Netch.csproj b/Netch/Netch.csproj
index 9891bf9f..9bb8860c 100644
--- a/Netch/Netch.csproj
+++ b/Netch/Netch.csproj
@@ -66,13 +66,14 @@
-
+
-
+
+
diff --git a/Netch/Utils/HttpProxyHandler/HttpWebServer.cs b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs
new file mode 100644
index 00000000..5605faa7
--- /dev/null
+++ b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs
@@ -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 _responderMethod;
+
+ public HttpWebServer(string[] prefixes, Func 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 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;
+ }
+ }
+
+ }
+}
diff --git a/Netch/Utils/HttpProxyHandler/PACListHandle.cs b/Netch/Utils/HttpProxyHandler/PACListHandle.cs
new file mode 100644
index 00000000..f8842e29
--- /dev/null
+++ b/Netch/Utils/HttpProxyHandler/PACListHandle.cs
@@ -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
+{
+ ///
+ /// 提供PAC功能支持
+ ///
+ class PACListHandle
+ {
+ public event EventHandler 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 IgnoredLineBegins = new[] { '!', '[' };
+
+ ///
+ /// 更新PAC文件(GFWList)
+ ///
+ //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 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 ParseResult(string response)
+ //{
+ // byte[] bytes = Convert.FromBase64String(response);
+ // string content = Encoding.ASCII.GetString(bytes);
+ // List valid_lines = new List();
+ // using (var sr = new StringReader(content))
+ // {
+ // foreach (var line in sr.NonWhiteSpaceLines())
+ // {
+ // if (line.BeginWithAny(IgnoredLineBegins))
+ // continue;
+ // valid_lines.Add(line);
+ // }
+ // }
+ // return valid_lines;
+ //}
+ }
+}
diff --git a/Netch/Utils/HttpProxyHandler/PACServerHandle.cs b/Netch/Utils/HttpProxyHandler/PACServerHandle.cs
new file mode 100644
index 00000000..84aefa7a
--- /dev/null
+++ b/Netch/Utils/HttpProxyHandler/PACServerHandle.cs
@@ -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
+{
+ ///
+ /// 提供PAC功能支持
+ ///
+ 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 lstProxy = new List();
+ 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";
+ }
+
+ ///
+ /// 获取PAC地址
+ ///
+ ///
+ 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;
+ }
+ }
+}
diff --git a/binaries b/binaries
index 4525fe9c..0b158dbc 160000
--- a/binaries
+++ b/binaries
@@ -1 +1 @@
-Subproject commit 4525fe9c71c8e0dda2b6e871212115219e5f44cf
+Subproject commit 0b158dbc5a5ad8c5f88170c5982d7d9cd1e915af