Open d4h0 opened 2 years ago
Is there any way, an attacker that got access to my system could use Vopono to execute arbitrary commands? Vopono seems to interact with several complex systems, so I guess even you can't be sure about that, but I may be wrong.
I just realized, that asking this was a bit dumb. Vopono itself, obviously, executes arbitrary commands, so setting NOPASSWD
for vopono
would anybody allow executing commands with root privileges...
I just use NOPASSWD all the time on my personal devices.
The NOPASSWD specific entry should work too.
The ideal option would be to use capabilities (we really only need sudo for the network namespace configuration), but I'm pretty certain there are still some areas lacking there. Another option would be to separate the network namespace creation from the process execution into separate binaries, although the execution part will still need enough capabilities to be able to execute in the new network namespace - it does a bind mount IIRC, I also did a bit of work trying to avoid shelling out in the unfinished libvopono.
Neither of those are small changes though.
I just use NOPASSWD all the time on my personal devices.
Are you not worried that everybody that gains access to your main user (physically, or via a remote exploit) easily can get root access?
Configuring docker
to not require authentication (which many people do) has the same problem (and I have decided to go through the pain of typing my password every time I use Docker).
The ideal option would be to use capabilities (we really only need sudo for the network namespace configuration), but I'm pretty certain there are still some areas lacking there.
Do you think running Vopono in a container would be easy to set up? This would make it possible to restrict what Vopono/root can do.
I also did a bit of work trying to avoid shelling out in the unfinished libvopono
Is libvopono
basically Vopono as a crate? I was wondering if there are any plans to publish the functionality of Vopono as a library. I think, that would be pretty useful (e.g. building GUIs for Vopono, or integrating the functionality in other applications (like a tool that switches the VPN every X minutes :))).
I might have found another way to do what I'm trying to archive.
Basically, the steps would be:
vopono
sudoers
entry for the vopono
user that enables it to execute the vopono
binary without authentication (vopono ALL=NOPASSWD:SETENV: /usr/bin/vopono
. SETENV:
is required, because Vopono uses sudo -E
)vopono
userThis way, I'd only have to type the password of the vopono
user when I start my script, and my regular user wouldn't be able to get root privileges without typing my password.
Do you see any problem with that approach?
I spent most of today to experiment with this idea (mostly researching how to do things), and when I thought I finished it, something broke... x)
I think this happened because I created and killed Vopono (and Privoxy) many times while creating my script.
When I run Vopono from my regular user (which previously always worked), I get the following output:
❯ vopono -v exec --custom /tmp/openvpn_test.ovpn --protocol openvpn --postup "echo '=> VPN is ready!'" "ls"
2022-05-16T19:45:26.032Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:26.038Z DEBUG vopono::pulseaudio > Setting PULSE_SERVER to /run/user/1000/pulse/native
2022-05-16T19:45:26.038Z INFO vopono::util > Calling sudo for elevated privileges, current user will be used as default user
2022-05-16T19:45:26.038Z DEBUG vopono::util > Args: ["vopono", "-v", "exec", "--custom", "/tmp/openvpn_test.ovpn", "--protocol", "openvpn", "--postup", "echo '=> VPN is ready!'", "ls"]
[sudo] password for dh:
2022-05-16T19:45:47.528Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.538Z DEBUG vopono::pulseaudio > Setting PULSE_SERVER to /run/user/1000/pulse/native
2022-05-16T19:45:47.538Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.539Z DEBUG vopono::util > Existing namespaces: []
2022-05-16T19:45:47.539Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.539Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.540Z DEBUG vopono::exec > vopono config.toml: configuration property "firewall" not found
2022-05-16T19:45:47.540Z DEBUG vopono::exec > vopono config.toml: configuration property "predown" not found
2022-05-16T19:45:47.540Z DEBUG vopono::exec > vopono config.toml: configuration property "user" not found
2022-05-16T19:45:47.540Z DEBUG vopono::exec > vopono config.toml: configuration property "dns" not found
2022-05-16T19:45:47.540Z DEBUG vopono::network_interface > ip addr
2022-05-16T19:45:47.541Z DEBUG vopono::exec > Interface: wlp4s0
2022-05-16T19:45:47.542Z DEBUG vopono::util > Existing namespaces: []
2022-05-16T19:45:47.542Z DEBUG vopono::util > ip netns add vopono_c_Dt2VWW2Ui1J
2022-05-16T19:45:47.544Z INFO vopono::netns > Created new network namespace: vopono_c_Dt2VWW2Ui1J
2022-05-16T19:45:47.545Z DEBUG vopono::util > Existing interfaces: 43: c_Dt2VWW2Ui1J_d@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 96:9e:36:fb:c7:df brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 10.200.1.1/24 scope global c_Dt2VWW2Ui1J_d
valid_lft forever preferred_lft forever
inet6 fe80::949e:36ff:fefb:c7df/64 scope link
valid_lft forever preferred_lft forever
2022-05-16T19:45:47.546Z DEBUG vopono::util > Assigned IPs: [10.200.1.1/24]
2022-05-16T19:45:47.546Z DEBUG vopono::netns > ip netns exec vopono_c_Dt2VWW2Ui1J ip addr add 127.0.0.1/8 dev lo
2022-05-16T19:45:47.548Z DEBUG vopono::netns > ip netns exec vopono_c_Dt2VWW2Ui1J ip link set lo up
STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN
connected full enabled enabled enabled enabled
2022-05-16T19:45:47.573Z DEBUG vopono::veth_pair > Detected NetworkManager running
2022-05-16T19:45:47.573Z DEBUG vopono::veth_pair > NetworkManager detected, adding c_Dt2VWW2Ui1J_d to unmanaged devices
2022-05-16T19:45:47.573Z DEBUG vopono::veth_pair > Appending to existing NetworkManager config file: /etc/NetworkManager/conf.d/unmanaged.conf
2022-05-16T19:45:47.573Z DEBUG vopono::util > nmcli connection reload
2022-05-16T19:45:47.586Z DEBUG vopono::veth_pair > firewalld not detected running
2022-05-16T19:45:47.586Z DEBUG vopono::util > ip link add c_Dt2VWW2Ui1J_d type veth peer name c_Dt2VWW2Ui1J_s
RTNETLINK answers: File exists
2022-05-16T19:45:47.587Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.587Z DEBUG vopono::util > nmcli connection reload
2022-05-16T19:45:47.600Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.600Z DEBUG vopono::util > Using config dir from $HOME config: /home/dh/.config
2022-05-16T19:45:47.600Z INFO vopono::netns > Shutting down vopono namespace - as there are no processes left running inside
2022-05-16T19:45:47.600Z DEBUG vopono::util > ip netns delete vopono_c_Dt2VWW2Ui1J
Error: Failed to create veth pair c_Dt2VWW2Ui1J_s, c_Dt2VWW2Ui1J_d
Caused by:
Command failed: ip link add c_Dt2VWW2Ui1J_d type veth peer name c_Dt2VWW2Ui1J_s
Do you have any idea, what the problem could be?
I guess, restarting my computer would fix the issue, but my script would basically start and kill Vopono similar often.
vopono list
doesn't return anything.
Regarding the troubleshooting information:
ip addr:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 68:f7:28:f8:32:e5 brd ff:ff:ff:ff:ff:ff
4: wlp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether cc:3d:82:39:ab:5c brd ff:ff:ff:ff:ff:ff
inet 192.168.179.30/24 brd 192.168.179.255 scope global dynamic noprefixroute wlp4s0
valid_lft 20554sec preferred_lft 20554sec
inet6 2001:9e8:a333:b501:bc2e:4324:c63:5c36/64 scope global dynamic noprefixroute
valid_lft 6767sec preferred_lft 3167sec
inet6 fe80::7071:540a:99b4:f306/64 scope link noprefixroute
valid_lft forever preferred_lft forever
5: br-2bf231161a79: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:3d:bf:4b:16 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-2bf231161a79
valid_lft forever preferred_lft forever
6: br-553dc8bf66cb: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:fd:b8:b2:00 brd ff:ff:ff:ff:ff:ff
inet 172.21.0.1/16 brd 172.21.255.255 scope global br-553dc8bf66cb
valid_lft forever preferred_lft forever
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8f:6a:2e:42 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
13: wwp0s20u10: <BROADCAST,MULTICAST,NOARP> mtu 1428 qdisc noop state DOWN group default qlen 1000
link/ether 76:85:1e:fe:fc:5b brd ff:ff:ff:ff:ff:ff
43: c_Dt2VWW2Ui1J_d@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 96:9e:36:fb:c7:df brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 10.200.1.1/24 scope global c_Dt2VWW2Ui1J_d
valid_lft forever preferred_lft forever
inet6 fe80::949e:36ff:fefb:c7df/64 scope link
valid_lft forever preferred_lft forever
ip link:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
link/ether 68:f7:28:f8:32:e5 brd ff:ff:ff:ff:ff:ff
4: wlp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT group default qlen 1000
link/ether cc:3d:82:39:ab:5c brd ff:ff:ff:ff:ff:ff
5: br-2bf231161a79: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:3d:bf:4b:16 brd ff:ff:ff:ff:ff:ff
6: br-553dc8bf66cb: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:fd:b8:b2:00 brd ff:ff:ff:ff:ff:ff
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:8f:6a:2e:42 brd ff:ff:ff:ff:ff:ff
13: wwp0s20u10: <BROADCAST,MULTICAST,NOARP> mtu 1428 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 76:85:1e:fe:fc:5b brd ff:ff:ff:ff:ff:ff
43: c_Dt2VWW2Ui1J_d@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 96:9e:36:fb:c7:df brd ff:ff:ff:ff:ff:ff link-netnsid 1
ping 10.200.1.2:
PING 10.200.1.2 (10.200.1.2) 56(84) bytes of data.
Seems to hang, nothing happens.
sudo nft list tables / sudo nft list table nat:
sudo: nft: command not found
sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE all -- 172.21.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE all -- 10.200.1.0/24 anywhere
MASQUERADE all -- 10.200.1.0/24 anywhere
MASQUERADE all -- 10.200.1.0/24 anywhere
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN all -- anywhere anywhere
RETURN all -- anywhere anywhere
sudo ip netns exec ping 10.200.1.1 / Cannot open network namespace "ping": No such file or directory:
Cannot open network namespace "ping": No such file or directory
sudo ip netns exec vopono_c_Dt2VWW2Ui1J ip addr / sudo ip netns exec vopono_c_Dt2VWW2Ui1J nft list tables / sudo ip netns exec vopono_c_Dt2VWW2Ui1J nft list table vopono_c_Dt2VWW2Ui1J / sudo ip netns exec vopono_c_Dt2VWW2Ui1J iptables -L:
Cannot open network namespace "vopono_c_Dt2VWW2Ui1J": No such file or directory
(I've taken vopono_c_Dt2VWW2Ui1J
from the log output of Vopono)
I'm using Arch and the 'aur/vopono-bin' package, in case that is relevant.
When I execute the command that failed, I get the following output:
$ sudo ip link add c_Dt2VWW2Ui1J_d type veth peer name c_Dt2VWW2Ui1J_s
RTNETLINK answers: File exists
So I guess, the cleanup didn't work when I killed Vopono.
Is there a way to trigger the cleanup somehow?
Are you not worried that everybody that gains access to your main user (physically, or via a remote exploit) easily can get root access?
It is an issue, but anything that runs as my user could already encrypt all my files, etc. anyway, so the best option is to only run trusted FOSS as much as possible.
Do you think running Vopono in a container would be easy to set up? This would make it possible to restrict what Vopono/root can do.
In theory it's possible, but it changes what the tool is/does. Like at the moment all of the hard work is in setting up the network namespace (and its firewall rules), and then it's just spawning processes inside that. If it were a container, you'd want to just do that in the container (to be fair, most of the code would be identical for the firewall, etc.), but then you need to set up bridging between the containers and presumably spawn your other app in a container too - which is problematic for torrent clients, etc. that need access to the host filesystem.
So it could mean much more configuration for the app side if you just want to run a normal web browser, etc. - it might be doable though. I actually used LXC for this back in 2015, and in the end I realised it was more effort than it was worth getting stuff like X forwarding to work, PulseAudio, etc. - and discovered network namespaces :slightly_smiling_face:
Is
libvopono
basically Vopono as a crate? I was wondering if there are any plans to publish the functionality of Vopono as a library. I think, that would be pretty useful (e.g. building GUIs for Vopono, or integrating the functionality in other applications (like a tool that switches the VPN every X minutes :))).
This would eventually be the idea, but it's quite a lot of work. Maybe I could start by just separating out the current code (even though it shells out) because it is pretty useful.
I also wrote a bit about the possibility for a GUI here - https://www.reddit.com/r/archlinux/comments/u1qj2v/vpn_kill_switches_do_not_always_work/i4g7dp5/?context=3 - it might be cool to do it though, even if it's just a simple PyTK thing for example.
Do you see any problem with that approach?
I think this is the best approach atm, and it's similar to what other tools do too (Jackett, etc.)
Error: Failed to create veth pair c_Dt2VWW2Ui1J_s, c_Dt2VWW2Ui1J_d Do you have any idea, what the problem could be?
Usually it means the kernel has updated and you need to reboot.
Is there a way to trigger the cleanup somehow?
Oops, it seems this is an edge case where somehow the lock file was deleted but the resources weren't deleted?
It's strange, usually if it fails to delete them the lockfile will still be there, and then it will delete them when you execute vopono next time.
I'd recommend deleting them manually (sudo ip link del XXX
) but if it happens again it's worth investigating.
I'd recommend deleting them manually (sudo ip link del XXX) but if it happens again it's worth investigating.
Thank you, @jamesmcm! That fixed it.
I guess this happened because I killed Vopono forcefully, and switched between users (my regular user, and the vopono
user). It seems, the lockfile is store in the user directory.
Haha, that's true. Because of that, I'm interested in switching to Qubes OS, which makes it easy to run special-purpose VMs (i.e. one VM for email, one for the browser, one for the dev environment, etc.).
Maybe I could start by just separating out the current code (even though it shells out) because it is pretty useful.
I think, that would be a great approach. The code that shells out can still be replaced gradually then.
I'd like to make Privoxy listen on an address that is only reachable from my machine, if possible. Would that be the following IP address?
2022-05-17T18:06:13.198Z DEBUG vopono::exec > Forwarding port: 8118, 10.200.1.2
If so, is there an easy way to access that IP from within the executed program/script, so I can generate the needed Privoxy config file?
I tried ip -json route get 8.8.8.8 | jq -r '.[].prefsrc
which gives me my local IP, when executed from outside Vopono. From within Vopono it gives me 10.236.11.121
instead of 10.200.1.2
, however.
When I execute Vopono there seem to be several errors:
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
ip6tables v1.8.7 (legacy): unknown reject type "icmp-net-unreachable"
sudo
isn't used correctly, once❯ vopono exec --custom /tmp/openvpn_test.ovpn --protocol openvpn --postup "echo '=> VPN is ready!'" -k -u root -f 8118 "privoxy --chroot --user privoxy --pidfile /tmp/privoxy.pid /etc/privoxy/config"
2022-05-17T18:46:59.324Z INFO vopono::util > Calling sudo for elevated privileges, current user will be used as default user
[sudo] password for dh:
2022-05-17T18:47:02.596Z INFO vopono::netns > Created new network namespace: vopono_c_Dt2VWW2Ui1J
STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN
connected full enabled enabled missing enabled
2022-05-17T18:47:02.698Z INFO vopono::netns > IP address of namespace as seen from host: 10.200.1.2
2022-05-17T18:47:02.698Z INFO vopono::netns > IP address of host as seen from namespace: 10.200.1.1
2022-05-17T18:47:02.702Z INFO vopono::openvpn > Launching OpenVPN...
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
ip6tables v1.8.7 (legacy): unknown reject type "icmp-net-unreachable"
Try `ip6tables -h' or 'ip6tables --help' for more information.
usage: sudo -h | -K | -k | -V
usage: sudo -v [-ABknS] [-g group] [-h host] [-p prompt] [-u user]
usage: sudo -l [-ABknS] [-g group] [-h host] [-p prompt] [-U user] [-u user] [command]
usage: sudo [-ABbEHknPS] [-C num] [-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user]
[VAR=value] [-i|-s] [<command>]
usage: sudo -e [-ABknS] [-C num] [-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] file ...
2022-05-17T18:47:09.345Z INFO vopono::exec > Application privoxy --chroot --user privoxy --pidfile /tmp/privoxy.pid /etc/privoxy/config launched in network namespace vopono_c_Dt2VWW2Ui1J with pid 6415
Bind /etc/netns/vopono_c_Dt2VWW2Ui1J/openvpn.log -> /etc/openvpn.log failed: No such file or directory
2022-05-17T18:47:10.372Z INFO vopono::exec > Keep-alive flag active - will leave network namespace alive until ctrl+C received
I get the same output with vopono exec --custom /tmp/openvpn_test.ovpn --protocol openvpn --postup "echo '=> VPN is ready!'" "ls"
, so it doesn't seem to be triggered by the Privoxy settings.
Is that something to worry about? The sudo
message seem odd to me.
I'd like to make Privoxy listen on an address that is only reachable from my machine, if possible. Would that be the following IP address?
2022-05-17T18:06:13.198Z DEBUG vopono::exec > Forwarding port: 8118, 10.200.1.2
If so, is there an easy way to access that IP from within the executed program/script, so I can generate the needed Privoxy config file?
Not at the moment, but it could be set like the $VOPONO_NS
env var is here: https://github.com/jamesmcm/vopono/blob/d9854ce4d5e6eddf2e8d9f7380c3ecb8235e73a1/src/netns.rs#L464
Regarding the errors, I think the OpenVPN log binding doesn't matter (it seems to read the log fine anyway).
But the ip6tables one may be an issue and seems to be related to this - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=515752 - I'll try to test that change, i..e checking we use icmp6-*
for ip6tables (personally I normally use nftables so I never saw this, although iptables is working okay on my Steam Deck at least).
The sudo one is strange, it's almost like it isn't quoting the command properly and is interpreting the other options as options for sudo :thinking:
After implementing #154 I was finally able to run Privoxy through Vopono!
With a bit of luck, I should be able to implement my 'VPN changer' script tomorrow (or rather, to test it. It basically is complete).
Do you think, this information would be useful to others and should be added to the user guide? Otherwise, I'd just post it here.
Yeah it'd be great to add it to the guide, I want to add instructions for Jackett too,
Is libvopono basically Vopono as a crate? I was wondering if there are any plans to publish the functionality of Vopono as a library. I think, that would be pretty useful (e.g. building GUIs for Vopono, or integrating the functionality in other applications (like a tool that switches the VPN every X minutes :))).
This would eventually be the idea, but it's quite a lot of work. Maybe I could start by just separating out the current code (even though it shells out) because it is pretty useful.
Have you seen netns-exec?
It seems to do something similar to Vopono, and seems to not shell out (and has only the nix
crate as dependency). Just in case, you are not sure how to replace some instances of shelling-out with pure Rust.
I've finally gotten my 'VPN changer' script working...
Doing this in Bash (as an example for the scripting guide), was pretty painful... I will write the real version most definitely not in Bash... ;)
The guide section is basically finished, but I'm going to wait with my PR until I've gotten my real use case working, which will probably be more like a Unix Socket-base API around Vopono. Just in case, I discover more caveats, or find out more useful information.
While developing the Bash script I sometimes got a few new errors:
[dh@arch bin]$ thread 'main' panicked at 'Failed to restore backup of NetworkManager unmanaged.conf: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/veth_pair.rs:187:22
2022-05-20T21:58:05.496Z WARN vopono::dns_config > Failed to delete network namespace directory: /etc/netns/vopono_c_Dt2VWW2Ui1J: Os { code: 2, kind: NotFound, message: "No such file or directory" }
Error: Could not process rule: No such file or directory
delete table inet vopono_nat
^^^^^^^^^^
thread 'main' panicked at 'Failed to delete nftables masquerade rule, ip_mask: 10.200.1.0/24, interface: wlp4s0', src/host_masquerade.rs:113:29
Is that something to worry about? Do I need to restore some config file somehow, like the backup of the NetworkManager
config file?
Thanks, I'll check that out. It's useful, tbh the only thing still requiring shelling out is setting the nftables firewall rules (but there are a lot of them) and iptables support too.
If the errors are only in the destructors just check that the state is okay afterwards (nothing left dirty). But that said, it would be good to fix the panics if you can pinpoint the causes?
If the errors are only in the destructors just check that the state is okay afterwards (nothing left dirty)
Yes, I believe the errors happened mostly during the teardown process. How would I check that the state is okay? Everything seems to work fine.
But that said, it would be good to fix the panics if you can pinpoint the causes?
I believe the errors happened only when my script wasn't able to kill previous Vopono instances*. When I then killed the script at some point via Ctrl-C
, the above errors were displayed.
So the errors should only happen when automating Vopono (and hopefully, my scripting section will help people to avoid these errors).
* The problem was basically, that Vopono restarts itself via sudo
if it wasn't started with root privileges. So if I executed vopono {options} &
in my script, sudo kill -INT $pid_of_bg_job
(and a ton of other commands and command variants to kill processes that I've tried... ;)) wouldn't kill Vopono. This happens, because the main Vopono process (which waits for the child process) doesn't handle SIGINT
, so sending SIGINT
to it, does nothing.
This took me longer to figure out, than I'd like to admit... x)
Oh, I see what you mean, only the one running with sudo handles SIGINT - https://github.com/jamesmcm/vopono/blob/master/src/exec.rs#L479-L507
In theory we could use another thread and a channel to do it with both processes, I'm not 100% sure how the sudo crate handles it though.
In theory we could use another thread and a channel to do it with both processes, I'm not 100% sure how the sudo crate handles it though.
I actually started implementing a fix, but when I figured out a workaround (just executing Vopono via sudo
directly), and I realized it still doesn't work (killing Vopno by the background job ID/PID), I stopped.
For some reason, sudo kill -INT
still can't kill Vopono if it is started via sudo vopono
.
When I read the man page of sudo
, I read that sudo
does and doesn't forward signals in some situations, so I thought it's normal that sudo
doesn't do it in this case.
But I just did an experiment:
$ sudo ls # Cache the password
$ sudo sleep 10m &
[1] 30256
$ sudo kill -INT 30256
$ jobs
[1]+ Interrupt sudo sleep 10m
...so it actually should work.
My workaround is to start Vopono directly via sudo
, get the PID of the sudo
process via jobs
, and then get the Vopono PID via ps --ppid $(jobs -pr) -o pid=
, which is easy enough (after figuring it out).
But this most likely should be fixed, if possible.
Besides reducing potential problems for other people who'd like to automate Vopono (and don't read the scripting guide), and making the guide a tiny bit easier, it would also eliminate one of the dependencies in my Rust version of the script.
Do you have any idea why Vopono started via sudo vopono {options} &
can't be killed via sudo kill -INT $(jobs -pr)
?
As far as I remember, that should work (if I remember the SIGINT
handling code correctly).
Vopono doesn't restart itself if it is already runs with root privileges, right?
Maybe I can have another look tomorrow. But I haven't as much time available anymore as I had last week, so I'm not sure if I can fix it now.
I also noticed that Vopono (if started without sudo
) doesn't return the exit code of the sudo
-ed process (it always returns 0
). Is there a reason for that? If not, that also should be fixed (as the return code of a program is often used in scripts).
What I forgot: Fixing the above probably also fix the issue that Vopono sometimes can't be killed via Ctrl-C (which happened to me a few times).
@jamesmcm: Is there any chance that your last commits have broken OpenVPN support?
I've updated my system (including Vopono), and now Vopono always hangs on:
2022-05-26T15:45:42.178Z DEBUG vopono::openvpn > 1653579942.178566 1 TCP/UDP: Preserving recently used remote address: [AF_INET]219.100.37.11:443
2022-05-26T15:45:42.178Z DEBUG vopono::openvpn > 1653579942.178600 2b000003 Socket Buffers: R=[131072->131072] S=[16384->16384]
2022-05-26T15:45:42.178Z DEBUG vopono::openvpn > 1653579942.178605 1 Attempting to establish TCP connection with [AF_INET]219.100.37.11:443 [nonblock]
After some time, I got the following output:
2022-05-26T15:47:42.295Z DEBUG vopono::openvpn > 1653580062.295219 1000021 TCP: connect to [AF_INET]219.100.37.11:443 failed: Connection timed out
2022-05-26T15:47:42.295Z DEBUG vopono::openvpn > 1653580062.295292 1 SIGUSR1[connection failed(soft),init_instance] received, process restarting
2022-05-26T15:47:42.295Z DEBUG vopono::openvpn > 1653580062.295304 21000003 Restart pause, 5 second(s)
2022-05-26T15:47:47.295Z DEBUG vopono::openvpn > 1653580067.295383 40 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.
2022-05-26T15:47:47.295Z DEBUG vopono::openvpn > 1653580067.295487 1 TCP/UDP: Preserving recently used remote address: [AF_INET]219.100.37.11:443
2022-05-26T15:47:47.295Z DEBUG vopono::openvpn > 1653580067.295507 2b000003 Socket Buffers: R=[131072->131072] S=[16384->16384]
2022-05-26T15:47:47.295Z DEBUG vopono::openvpn > 1653580067.295511 1 Attempting to establish TCP connection with [AF_INET]219.100.37.11:443 [nonblock]
2022-05-26T15:49:47.409Z DEBUG vopono::openvpn > 1653580187.409558 1000021 TCP: connect to [AF_INET]219.100.37.11:443 failed: Connection timed out
2022-05-26T15:49:47.409Z DEBUG vopono::openvpn > 1653580187.409634 1 SIGUSR1[connection failed(soft),init_instance] received, process restarting
2022-05-26T15:49:47.409Z DEBUG vopono::openvpn > 1653580187.409646 21000003 Restart pause, 5 second(s)
2022-05-26T15:49:52.409Z DEBUG vopono::openvpn > 1653580192.409730 40 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.
2022-05-26T15:49:52.409Z DEBUG vopono::openvpn > 1653580192.409826 1 TCP/UDP: Preserving recently used remote address: [AF_INET]219.100.37.11:443
2022-05-26T15:49:52.409Z DEBUG vopono::openvpn > 1653580192.409849 2b000003 Socket Buffers: R=[131072->131072] S=[16384->16384]
2022-05-26T15:49:52.409Z DEBUG vopono::openvpn > 1653580192.409854 1 Attempting to establish TCP connection with [AF_INET]219.100.37.11:443 [nonblock]
Hi,
Thank you so much for creating Vopono! So far, it seems to work very well :)
I'm wondering what the best way would be to script Vopono.
For example, let's say, I'd like to change my VPN connection every 30 minutes, and I'm running Privoxy within Vopono (this way, I could just configure my browser to use Privoxy as HTTP proxy, and I wouldn't have to restart my browser every 30 minutes):
$ vopono -v exec --provider azirevpn -k -u root -f 8118 --server norway "privoxy --chroot --user privoxy /etc/privoxy/config"
The scripting part would be easy, of course, but after 30 minutes (I believe) the script would ask for my password again.
What would be the best way to avoid this?
For example, I could run my script as root. But that seems to lead to problems with Vopono (from the issues I've read). Besides that, for the obvious reasons, I'd like to avoid running my script as root.
Another option would be to switch to passwordless sudo (disabling the requirement to enter the password, when executing a command via
sudo
), which I would like to avoid as well.It seems, the SUDO_ASKPASS environment variable could be used to provide the password, but I'm not sure how to do this securely.
The last option I see, would be to set
NOPASSWD
only for/usr/bin/vopono
viasudoers
:my_user host_name=NOPASSWD: /usr/bin/vopono
This looks the most promising to me, but I never did something like this, and I have no clue if that would be secure.
Is there any way, an attacker that got access to my system could use Vopono to execute arbitrary commands? Vopono seems to interact with several complex systems, so I guess even you can't be sure about that, but I may be wrong.
If this option turns out to be secure, I believe it would be good to add it to the
systemd
section of the user guide. You are mentioning passwordless sudo access, but I interpreted this as "passwordless sudo access for everything". But maybe this interpretation is wrong, and you meant settingNOPASSWD
only forvopono
.Thanks again, for your work! :)