diff --git a/examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs b/examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
index 0342ef62f..2b933fdf0 100644
--- a/examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
+++ b/examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
@@ -105,7 +105,10 @@ public MainWindow()
};
proxyServer.Start();
- proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
+ var proxyLocalhostTraffic = new SystemProxyBypassRuleSet()
+ .SubtractImplicitBypassRules();
+
+ proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp, proxyLocalhostTraffic);
InitializeComponent();
}
diff --git a/src/Titanium.Web.Proxy/Helpers/SystemProxy.cs b/src/Titanium.Web.Proxy/Helpers/SystemProxy.cs
index 38a237c5a..60aa03820 100644
--- a/src/Titanium.Web.Proxy/Helpers/SystemProxy.cs
+++ b/src/Titanium.Web.Proxy/Helpers/SystemProxy.cs
@@ -84,7 +84,8 @@ public SystemProxyManager()
///
///
///
- internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType)
+ ///
+ internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType, string bypassRules)
{
using (var reg = OpenInternetSettingsKey())
{
@@ -106,6 +107,7 @@ internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType
reg.SetValue(RegProxyEnable, 1);
reg.SetValue(RegProxyServer,
string.Join(";", existingSystemProxyValues.Select(x => x.ToString()).ToArray()));
+ reg.SetValue(RegProxyOverride, bypassRules);
Refresh();
}
diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs
index 4fa65f853..3aa30a4e8 100644
--- a/src/Titanium.Web.Proxy/ProxyServer.cs
+++ b/src/Titanium.Web.Proxy/ProxyServer.cs
@@ -452,6 +452,16 @@ public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint)
SetAsSystemProxy(endPoint, ProxyProtocolType.Http);
}
+ ///
+ /// Set the given explicit end point as the default proxy server for current machine.
+ ///
+ /// The explicit endpoint.
+ /// The system proxy bypass rules.
+ public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint, SystemProxyBypassRuleSet bypassRules)
+ {
+ SetAsSystemProxy(endPoint, ProxyProtocolType.Http, bypassRules);
+ }
+
///
/// Set the given explicit end point as the default proxy server for current machine.
///
@@ -461,12 +471,33 @@ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
SetAsSystemProxy(endPoint, ProxyProtocolType.Https);
}
+ ///
+ /// Set the given explicit end point as the default proxy server for current machine.
+ ///
+ /// The explicit endpoint.
+ /// The system proxy bypass rules.
+ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint, SystemProxyBypassRuleSet bypassRules)
+ {
+ SetAsSystemProxy(endPoint, ProxyProtocolType.Https, bypassRules);
+ }
+
///
/// Set the given explicit end point as the default proxy server for current machine.
///
/// The explicit endpoint.
/// The proxy protocol type.
public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
+ {
+ SetAsSystemProxy(endPoint, protocolType, new SystemProxyBypassRuleSet());
+ }
+
+ ///
+ /// Set the given explicit end point as the default proxy server for current machine.
+ ///
+ /// The explicit endpoint.
+ /// The proxy protocol type.
+ /// The system proxy bypass rules.
+ public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType, SystemProxyBypassRuleSet bypassRules)
{
if (SystemProxySettingsManager == null)
throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
@@ -500,7 +531,8 @@ public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType p
? "localhost"
: endPoint.IpAddress.ToString(),
endPoint.Port,
- protocolType);
+ protocolType,
+ bypassRules?.ToString() ?? string.Empty);
if (isHttp) endPoint.IsSystemHttpProxy = true;
diff --git a/src/Titanium.Web.Proxy/SystemProxyBypassRuleSet.cs b/src/Titanium.Web.Proxy/SystemProxyBypassRuleSet.cs
new file mode 100644
index 000000000..6805d2079
--- /dev/null
+++ b/src/Titanium.Web.Proxy/SystemProxyBypassRuleSet.cs
@@ -0,0 +1,72 @@
+using System.Collections.Generic;
+namespace Titanium.Web.Proxy;
+
+///
+///
+/// This class is used to control when system should skip or use (in case of implicitly ignored addresses) system proxy.
+/// By default for secutiry reasons proxy is ignored on local networks considered as trusted, you can disable it by using .
+/// Be aware that rules are check in order they are added, it's important when they are contradicting.
+///
+public class SystemProxyBypassRuleSet
+{
+ private const string IgnoreImplicitBypassRules = "<-loopback>";
+ private const string BypassSimpleHostnamesRule = "";
+
+ private readonly List _bypassRules;
+
+ ///
+ /// Initialize new system proxy rule set.
+ ///
+ public SystemProxyBypassRuleSet()
+ {
+ _bypassRules = new List();
+ }
+
+ ///
+ /// Adds user defined rule to bypass system proxy.
+ ///
+ /// Rule specifying which urls should not go though system proxy.
+ /// Itself.
+ ///
+ ///
+ /// var ruleSet =
+ /// new SystemProxyBypassRuleSet()
+ /// .AddRule("https://x.*.y.com:99")
+ /// .AddRule("*foobar.com")
+ /// .AddRule("*.org:443")
+ /// .AddRule("192.168.1.1/16");
+ ///
+ ///
+ public SystemProxyBypassRuleSet AddRule(string rule)
+ {
+ _bypassRules.Add(rule);
+ return this;
+ }
+
+ ///
+ /// Adds rule for bypassing hostnames without a period in them, and that are not IP literals.
+ ///
+ /// Itself.
+ public SystemProxyBypassRuleSet AddSimpleHostnames()
+ {
+ _bypassRules.Add(BypassSimpleHostnamesRule);
+ return this;
+ }
+
+ ///
+ /// Subtracts the implicit proxy bypass rules (localhost and link local addresses).
+ /// This is generally only needed for test setups. Beware of the security implications to proxying localhost.
+ /// Ordering may matter when using a subtractive rule, as rules will be evaluated in a left-to-right order.
+ ///
+ /// Itself.
+ public SystemProxyBypassRuleSet SubtractImplicitBypassRules()
+ {
+ _bypassRules.Add(IgnoreImplicitBypassRules);
+ return this;
+ }
+
+ public override string ToString()
+ {
+ return string.Join(";", _bypassRules);
+ }
+}
diff --git a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
index ccd580dc5..bce3d9679 100644
--- a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+++ b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
@@ -1,7 +1,7 @@
- net461;net60
+ net48;net60
Titanium.Web.Proxy
false
True
diff --git a/tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs b/tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
index 5cbb62d8b..12c37446c 100644
--- a/tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
+++ b/tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
@@ -19,13 +19,13 @@ public void CompareProxyAddressReturnedByWebProxyAndWinHttpProxyResolver()
{
CompareUrls();
- proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Http);
+ proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Http, string.Empty);
CompareUrls();
- proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Https);
+ proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Https, string.Empty);
CompareUrls();
- proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.AllHttp);
+ proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.AllHttp, string.Empty);
CompareUrls();
// for this test you need to add a proxy.pac file to a local webserver