Open piramiday opened 3 years ago
Absolutely agree, this would be a great feature. Mainly just needs some new interface in piactl to add/remove apps, since the infrastructure to get and set preferences is already there.
We do have the clunky way now with the --unstable applysettings
command, which lets you modify the settings JSON more-or-less directly. This uses the same mechanism the GUI uses to apply settings. (It's behind "--unstable" because the JSON structure could change, but historically it has been stable.)
The settings structure is documented in settings.h, for example here's the definition of a "split tunnel application rule": https://github.com/pia-foss/desktop/blob/508b67e66a89ed44401dde5849f00ae47473b4d5/common/src/settings.h#L956
# These work on all platforms, on Windows be aware that the shell quoting will differ
# Enable split tunnel
$ piactl -u applysettings '{"splitTunnelEnabled":true}'
# Set the split tunnel app rules. This replaces any existing rules.
# Appending would need to dump the existing rules (piactl -u dump daemon-settings)
# and use something like 'jq' to manipulate the rules.
# 'path' is an executable path on Win/Linux or an app bundle path on macOS.
# 'mode' is 'exclude' for "bypass" or 'include' for "only VPN".
$ piactl -u applysettings '{"splitTunnelRules": [ {"path":"/usr/lib/firefox/firefox","mode":"exclude"}, {"path":"/usr/lib/chromium/chromium","mode":"include"} ]}'
# Set the split tunnel IP rules. Again, replaces any existing rules.
# Use CIDR notation for the subnet. Use /32 for an exact IPv4 IP only (or /128 for IPv6).
# 'mode' must always be exclude, no other modes currently exist for subnet rules.
$ piactl -u applysettings '{"bypassSubnets": [ {"mode":"exclude", "subnet":"172.16.0.0/16"} ] }'
# The "fixed rules" for Routed Packets, All Other Apps, and split tunnel Name Servers are all
# boolean settings.
$ piactl -u applysettings '{"defaultRoute":true}' # All Other Apps = Use VPN
$ piactl -u applysettings '{"routedPacketsOnVPN":true}' # Routed Packets = Use VPN
$ piactl -u applysettings '{"splitTunnelDNS":true}' # Name Servers = Follow App Rules
It'd be awesome to get a proper interface for split tunnel settings, but for now 'applysettings' can hopefully do what you need.
great, thanks, I'll try it out. do I need to piactl connect
after such applysettings
lines?
Generally, yes - and a piactl connect
when connected with no reconnect needed is just ignored anyway, so you can just fire it off and let the daemon decide.
Specifically, defaultRoute
and splitTunnelDNS
always require a reconnect; splitTunnelEnabled
usually does depending on the other settings. App and IP rules don't require a reconnect (though you may need to restart the app, depending on the app). needsReconnect
is set in daemon state whenever a reconnect is needed.
great stuff, thanks! :+1:
I'm okay with the clunky command (for now) -- feel free to close this issue, or to leave it open as a placeholder for the feature request.
while we are at it, though, how come nobody from PIA patrols the "community" portal? all requests appear as "awaiting review"...
I'll leave it open - I think it's a great feature idea. I'm not sure where it will fall on our priorities list with everything we have in the pipeline, but if somebody wandered across this issue and wanted to put together a PR, that'd be amazing :star_struck:
That's a great question re: the community portal, I'll see what I can find out about that.
Thanks for checking on the community portal - this was recently handed over to our CS team, and they're going to review issues monthly to send out to each department. There are some good suggestions on there that I'd like to get on our roadmap!
quick follow up question: let's say that I would like to directly intervene on the system config without reconnecting PIA. is it doable? what should I do, broadly?
if I add my fresh IP to the allowed list like so:
user@host:~$ sudo iptables -I piavpn.r.305.allowSubnets 1 -j ACCEPT -d 12.34.56.78/32
which seems to me to be the only modification that PIA applies, well, it does not work.
if instead I act directly on the OUTPUT
chain and then add my IP to the routing table, then it works:
user@host:~$ sudo iptables -I OUTPUT 1 -j ACCEPT -d 12.34.56.78/32
user@host:~$ sudo route add -host 12.34.56.78/32 gw 10.0.0.1
what am I missing? thanks.
Hi @piramiday - the way we manage routing for split tunnel subnets is a little different than tradtional routing rules. We mark packets heading towards split subnets with the "excludePacketTag", see here: https://github.com/pia-foss/desktop/blob/master/daemon/src/posix/posix_firewall_iptables.cpp#L976-L984
This mark is then used by our routing policies to route the traffic out the physical interface.
If you add rules of the form -d <your subnet> -j MARK --set-mark 12817
to the piavpn.r.90.tagSubnets
chain in the mangle table, it should work as expected.
I have just tried but unfortunately it does not seem to be working:
$ sudo iptables -I INPUT 1 -s 12.34.56.78/32 -j ACCEPT
$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 12.34.56.78 anywhere
[...]
$ sudo iptables -I piavpn.r.305.allowSubnets -d 12.34.56.78/32 -j ACCEPT
$ sudo iptables -L piavpn.r.305.allowSubnets
Chain piavpn.r.305.allowSubnets (1 references)
target prot opt source destination
ACCEPT all -- anywhere 12.34.56.78
$ sudo iptables -t mangle -I piavpn.r.90.tagSubnets -d 12.34.56.78/32 -j MARK --set-mark 12817
$ sudo iptables -t mangle -L piavpn.r.90.tagSubnets
Chain piavpn.r.90.tagSubnets (1 references)
target prot opt source destination
MARK all -- anywhere 12.34.56.78 MARK set 0x3211
any thoughts? thanks.
Hm, I would suggest adding a rule via the app - confirm that works - then look at the content of these chains for that app-added subnet. Then reproduce that for your custom subnets.
After doing that, if that fails to work, i can look into it more deeply, but let's make sure we check that box first 😛
with respect to my old post, the problem was that yet another rule in the mangle
table was needed.
minimal script:
IP=12.34.56.78
sudo iptables -t filter -A piavpn.r.305.allowSubnets -d "$1/32" -j ACCEPT
sudo iptables -t mangle -A piavpn.r.200.tagFwdSubnets -d "$1/32" -j MARK --set-mark 12817
sudo iptables -t mangle -A piavpn.r.90.tagSubnets -d "$1/32" -j MARK --set-mark 12817
which of course will be applied if splitTunnelEnabled
is set to true
.
still, it is perfectly reasonable to have piactl
directly insert rules using iptables
without having to reconnect whenever the user wants to add an excluded IP address.
it would be awesome to have some kind of command-line capability for this, which was the original point of my issue.
on a related note, it would be useful to have a way to add an IP to an already-present list of excluded IPs, instead of specifying the entire JSON bypassSubnets
list with the unstable applysettings
command.
I will then leave this issue open as a reminder that such features would be quite useful.
+1 for the feature
Hi. Meet the same issue. After some debugging found next cli only workaround.
Stop the vpn service:
sudo systemctl stop piavpn
Find where your pia ctl dir located (if you don't know yet):
systemctl cat piavpn | grep 'ExecStart'
Edit PIA VPN configuration file, add your required ip/subnet:
sudo vi /opt/piavpn/etc/settings.json
I need to set bypass only for ip so I changed only these keys:
bypassSubnets
splitTunnelDNS
splitTunnelEnabled
According to your need you can play with other sections. The simplest way - set required configuration in UI, close Settings and review configuration file.
I have not found example in Google so here is a full example of my configuration for your reference:
{
"allowLAN": true,
"automaticTransport": true,
"automationEnabled": false,
"automationRules": [],
"betaUpdateChannel": "beta",
"blockIPv6": true,
"bypassSubnets": [
{
"mode": "exclude",
"subnet": "121.78.53.64/29"
}
],
"cipher": "AES-128-GCM",
"connectOnLaunch": false,
"defaultRoute": true,
"desktopNotifications": true,
"enableMACE": false,
"favoriteLocations": [],
"includeGeoOnly": true,
"killswitch": "auto",
"largeLogFiles": false,
"lastDismissedAppMessageId": 0,
"lastUsedVersion": "3.3.1+06924",
"localPort": 0,
"location": "auto",
"macStubDnsMethod": "NX",
"manualServer": {
"cn": "",
"correspondingRegionId": "",
"ip": "",
"openvpnNcpSupport": false,
"openvpnTcpPorts": [],
"openvpnUdpPorts": [],
"serviceGroups": []
},
"method": "openvpn",
"mtu": -1,
"offerBetaUpdates": false,
"overrideDNS": "pia",
"persistDaemon": true,
"portForward": false,
"primaryModules": [
"region",
"ip"
],
"protocol": "udp",
"proxyCustom": {
"host": "",
"password": "",
"port": 0,
"username": ""
},
"proxyEnabled": false,
"proxyShadowsocksLocation": "auto",
"proxyType": "shadowsocks",
"ratingEnabled": true,
"recentLocations": [],
"remotePortTCP": 0,
"remotePortUDP": 0,
"routedPacketsOnVPN": true,
"secondaryModules": [
"quickconnect",
"performance",
"usage",
"settings",
"account"
],
"serviceQualityAcceptanceVersion": "",
"sessionCount": 12,
"showAppMessages": true,
"splitTunnelDNS": true,
"splitTunnelEnabled": true,
"splitTunnelRules": [],
"successfulSessionCount": 9,
"surveyRequestEnabled": true,
"themeName": "dark",
"updateChannel": "release",
"windowsIpMethod": "dhcp",
"wireguardPingTimeout": 60,
"wireguardUseKernel": true
}
Start VPN service again:
sudo systemctl start piavpn
Turn on VPN connection:
piactl connect
Review your iptables
configuration to confirm that rules for your ip-s have been applied:
iptables -S | grep allowSubnets
-N piavpn.305.allowSubnets -N piavpn.a.305.allowSubnets -N piavpn.r.305.allowSubnets -A piavpn.305.allowSubnets -j piavpn.r.305.allowSubnets -A piavpn.a.305.allowSubnets -j piavpn.305.allowSubnets -A piavpn.anchors -j piavpn.a.305.allowSubnets -A piavpn.r.305.allowSubnets -d 121.78.53.64/29 -j ACCEPT
hey @val-olfr, your comment is thorough but unnecessary. :rabbit:
as a brief recap, let me explain that the problem is twofold.
how to modify settings from the command line? clunky but solved!
you can specify your custom "bypass subnet" parameter with the applysettings
command:
$ piactl -u applysettings '{"bypassSubnets": [ {"mode":"exclude", "subnet":"172.16.0.0/16"} ] }'
(as quoted from https://github.com/pia-foss/desktop/issues/34#issuecomment-916072320, which works well.)
of course you need to have the other parameters consistently set, eg splitTunnelEnabled
set to true, etc.
most importantly, you need to reconnect so that PIA might add the new entries to iptables
.
how to accomplish the same without reconnecting? clunky but solved! that is the point of my previous post: https://github.com/pia-foss/desktop/issues/34#issuecomment-1079964700 just a few lines of code and no reconnect necessary.
your comment forgets about the applysettings
command and skips over my three-liner to solve the iptables problem without reconnecting. :rocket:
it would be useful for all headless installations to be able to control split-tunneling via the command-line
piactl
tool.for the time being, it would be awesome to get some clunky way to accomplish the same result, e.g. hard modifying the preferences to simulate what the GUI would have done, etc.
the feature has been proposed here, as well: https://www.privateinternetaccess.com/helpdesk/community/view/split-tunnelling-through-command-line