Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

option to exclude other IPs from the VPN #2138

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public partial class OutlineService : ServiceBase
private static string[] IPV4_RESERVED_SUBNETS = {
"0.0.0.0/8",
"10.0.0.0/8",
"127.0.0.0/8",
"100.64.0.0/10",
"169.254.0.0/16",
"172.16.0.0/12",
Expand All @@ -103,6 +104,7 @@ public partial class OutlineService : ServiceBase
private EventLog eventLog;
private NamedPipeServerStream pipe;
private string proxyIp;
private String[] excludedIPs;
private string gatewayIp;
private int gatewayInterfaceIndex;

Expand Down Expand Up @@ -332,17 +334,57 @@ private void HandleRequest(ServiceRequest request)
switch (request.action)
{
case ACTION_CONFIGURE_ROUTING:
ConfigureRouting(request.parameters[PARAM_PROXY_IP], Boolean.Parse(request.parameters[PARAM_AUTO_CONNECT]));
ConfigureRouting(request.parameters[PARAM_PROXY_IP],request.excludedIPs, Boolean.Parse(request.parameters[PARAM_AUTO_CONNECT]));
break;
case ACTION_RESET_ROUTING:
ResetRouting(proxyIp, gatewayInterfaceIndex);
ResetRouting(proxyIp,excludedIPs, gatewayInterfaceIndex);
break;
default:
eventLog.WriteEntry($"Received invalid request: {request.action}", EventLogEntryType.Error);
break;
}
}

private Boolean ThisNetworkContains(String rawIP)

{



IPAddress IPReal = IPAddress.Parse(rawIP);

foreach (var network in IPV4_RESERVED_SUBNETS)

{







IPNetwork2 iPnetwork = IPNetwork2.Parse(network);

if (iPnetwork.Contains(IPReal))

{

return true;

}





}



return false;

}

// Routes all traffic *except that destined for the proxy server*
// through the TAP device, creating the illusion of a system-wide VPN.
//
Expand Down Expand Up @@ -390,7 +432,7 @@ private void HandleRequest(ServiceRequest request)
// TODO: The client needs to handle certain autoconnect failures better,
// e.g. if IPv4 redirect fails then the client is not really in
// the reconnecting state; the system is leaking traffic.
public void ConfigureRouting(string proxyIp, bool isAutoConnect)
public void ConfigureRouting(string proxyIp, String[] excluded, bool isAutoConnect)
{
try
{
Expand All @@ -409,10 +451,31 @@ public void ConfigureRouting(string proxyIp, bool isAutoConnect)
eventLog.WriteEntry($"connecting via gateway at {gatewayIp} on interface {gatewayInterfaceIndex}");

// Set the proxy escape route first to prevent a routing loop when capturing all IPv4 traffic.

try
{
AddOrUpdateProxyRoute(proxyIp, gatewayIp, gatewayInterfaceIndex);
eventLog.WriteEntry($"created route to proxy");

if (excluded != null)

{

eventLog.WriteEntry("extra IP exclude");

foreach (string excludedIp in excluded)

{

AddOrUpdateProxyRoute(excludedIp, gatewayIp, gatewayInterfaceIndex);

eventLog.WriteEntry($"created extra IP route to proxy excluded {excludedIp}");

}

this.excludedIPs = excluded;

}
}
catch (Exception e)
{
Expand Down Expand Up @@ -473,7 +536,7 @@ public void ConfigureRouting(string proxyIp, bool isAutoConnect)
// function is called while Outline is not connected. This route is
// mostly harmless because it only affects traffic to the proxy and
// if/when the user reconnects to it the route will be updated.
public void ResetRouting(string proxyIp, int gatewayInterfaceIndex)
public void ResetRouting(string proxyIp, String[] excluded, int gatewayInterfaceIndex)
{
try
{
Expand Down Expand Up @@ -502,6 +565,48 @@ public void ResetRouting(string proxyIp, int gatewayInterfaceIndex)
eventLog.WriteEntry($"failed to unblock IPv6: {e.Message}", EventLogEntryType.Error);
}

if (excluded != null)

{



eventLog.WriteEntry("extra IP to exclude");

foreach (var excludedIP in excluded)

{



try

{

DeleteProxyRoute(excludedIP);

eventLog.WriteEntry($"deleted extra IP route to proxy {excludedIP}");

}

catch (Exception e)

{

eventLog.WriteEntry($"failed to delete route to proxy: {e.Message}", EventLogEntryType.Error);

}

}





this.excludedIPs = null;

}

if (proxyIp != null)
{
try
Expand Down Expand Up @@ -620,6 +725,16 @@ private void StopSmartDnsBlock()

private void AddOrUpdateProxyRoute(string proxyIp, string gatewayIp, int gatewayInterfaceIndex)
{

//check if proxy IP belongs to local network then do nothing
if (ThisNetworkContains(proxyIp))

{

return;

}

// "netsh interface ipv4 set route" does *not* work for us here
// because it can only be used to change a route's *metric*.
try
Expand All @@ -634,6 +749,14 @@ private void AddOrUpdateProxyRoute(string proxyIp, string gatewayIp, int gateway

private void DeleteProxyRoute(string proxyIp)
{
//check if proxy IP belongs to local network then do nothing
if (ThisNetworkContains(proxyIp))

{

return ;

}
// "route" doesn't need to know on which interface or through which
// gateway the route was created.
RunCommand(CMD_ROUTE, $"delete {proxyIp}");
Expand Down Expand Up @@ -1063,6 +1186,9 @@ internal class ServiceRequest
internal string action;
[DataMember]
internal Dictionary<string, string> parameters;
[DataMember]

internal String[] excludedIPs;
}

[DataContract]
Expand Down