Skip to content

Commit 2d2b63a

Browse files
authored
Merge pull request #264 from jamesmcm/command_fixes
Fix command parsing, add env var, host entry
2 parents 44e4849 + 5eea56e commit 2d2b63a

12 files changed

+279
-110
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ basic_tcp_proxy = "0.3.2"
3232
strum = "0.26"
3333
strum_macros = "0.26"
3434
shellexpand = { version = "3", features = ["full"] }
35+
shell-words = "1"
3536

3637
[package.metadata.rpm]
3738
package = "vopono"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ See the [vopono User Guide](USERGUIDE.md) for much more detailed usage instructi
108108
Install the `vopono-git` package with your favourite AUR helper.
109109

110110
```bash
111-
$ yay -S vopono-git
111+
$ paru -S vopono-git
112112
$ vopono sync
113113
```
114114

USERGUIDE.md

+90-36
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,55 @@ Note that the values are case-sensitive. If you use a custom config file
6161
then you should not set the provider or server (setting the protocol is
6262
also optional).
6363
64-
The current network namespace name is provided to the PostUp and PreDown
65-
scripts in the environment variable `$VOPONO_NS`. It is temporarily set
66-
when running these scripts only.
64+
### PostUp and PreDown scripts - run on Host (outside network namespace)
6765
68-
Similarly, the network namespace IP address is provided via `$VOPONO_NS_IP`,
69-
and is available to the PostUp and PreDown scripts, and the application to
70-
run itself. `$VOPONO_NS_IP` is useful if you'd like to configure a server
66+
vopono can run scripts on the host machine (outside the network namespace) with the `--postup` and `--predown` arguments (or set in the `~/.config/vopono/config.toml` file). The postup script will run right after the network namespace is set up (also after provider port forwarding if used), the postdown script will run when tearing down the network namespace after the target application has terminated.
67+
68+
These scripts run outside of the network namespace so that they can be used to run proxies and DNS services which the network namespace can use. To run extra commands within the network namespace, you can just wrap the target command with your own script (see the Plex example below).
69+
70+
These scripts run using the current working directory with the same user as the target application itself (which can be set
71+
with the `user` argument or config file entry).
72+
73+
Arguments can be passed to the scripts from the command line (note the escaped spaces if the script path contains spaces), e.g.:
74+
75+
```bash
76+
--postup "~/test\ postup.sh argy1 argy2"
77+
```
78+
79+
e.g. with a script like:
80+
81+
```bash
82+
#!/bin/bash
83+
echo "arg1: $1 arg2: $2"
84+
```
85+
86+
Just like for the target application execution, the following environment variables are available (but recall that these scripts run *outside* the network namespace):
87+
88+
- `$VOPONO_HOST_IP` the local IP address of the host machine as seen from inside the network namespace.
89+
- `$VOPONO_NS_IP` the local IP address of the network namespace as seen from the host.
90+
- `$VOPONO_NS` the name of the network namespace.
91+
- `$VOPONO_FORWARDED_PORT` the forwarded port for provider port forwarding (ProtonVPN or PIA) - only when using `--port-forwarding` or `--custom-port-forwarding`
92+
93+
`$VOPONO_NS_IP` is useful if you'd like to configure a server
7194
running within the network namespace to listen on its local IP address only
72-
(see below, for more information on that).
95+
(see below for more information on that).
7396
74-
The application to run within the namespace also has access to
75-
`$VOPONO_HOST_IP`, to get the IP address of the host.
97+
### Host access from within the network namespace
7698
77-
Note: These environment variables are currently only available from within
78-
the application/script to run, not on the command line. So the following
79-
doesn't work:
99+
The host IP address (as seen from inside the network namespace) is provided as the
100+
`$VOPONO_HOST_IP` environment variable to the target application/script itself (and also the host scripts described above).
80101
81-
`vopono exec {other Vopono options} 'echo "HOST IP: $VOPONO_HOST_IP"'`
102+
If `--allow-host-access` is set then the host machine IP (as seen from the network namespace) is also added to the hosts file as `vopono.host` so you can access services on the host machine from within the network namespace e.g. at `http://vopono.host:8080` etc.
82103
83-
Output: `HOST IP: $VOPONO_HOST_IP` (the environ variable wasn't expanded).
104+
If provider port forwarding is enabled (e.g. `--port-forwarding` or `--custom-port-forwarding` with ProtonVPN or PIA) then the forwarded port is provided as `$VOPONO_FORWARDED_PORT`.
84105
85-
A work around is to create a executable script, that executes the
86-
application you'd like to run:
106+
### Running commands before and after execution within the network namespace
107+
108+
To run extra commands inside the network namespace you can wrap your target application with a bash script and provide that script as the target to vopono.
109+
110+
Note that the target user *must* have read and executable access to this script!
111+
112+
For example with a simple script using the environment variables (also see the Plex section below):
87113
88114
```bash
89115
#!/bin/bash
@@ -101,32 +127,14 @@ Output:
101127
=> HOST IP: 10.200.1.1
102128
```
103129
104-
### Host scripts
105-
106-
Host scripts to run just after a network namespace is created and just before it is destroyed,
107-
can be provided with the `postup` and `predown` arguments (or in the `config.toml`).
108-
109-
Note these scripts run on the host (outside the network namespace), using the current working directory,
110-
and with the same user as the final application itself (which can be set
111-
with the `user` argument or config file entry).
112-
113-
Script arguments (e.g. `script.sh arg1 arg1`), are currently not possible, resulting in an error:
114-
115-
```
116-
$ vopono exec {other Vopono options} --postup 'echo POSTUP' ls
117-
[...]
118-
sudo: echo POSTUP: command not found
119-
[...]
120-
```
121-
122130
### Wireguard
123131
124132
Install vopono and use `vopono sync` to
125133
create the Wireguard configuration files (and generate a keypair if
126134
necessary):
127135
128136
```bash
129-
$ yay -S vopono-git
137+
$ paru -S vopono-bin
130138
$ vopono sync
131139
```
132140
@@ -159,7 +167,7 @@ Install vopono and use `vopono sync` to
159167
create the OpenVPN configuration files and server lists.
160168
161169
```bash
162-
$ yay -S vopono-git
170+
$ paru -S vopono-bin
163171
$ vopono sync
164172
```
165173
@@ -386,6 +394,52 @@ $ vopono -v exec -u jackett "/usr/lib/jackett/jackett --NoRestart --NoUpdates --
386394
387395
You can then access the web UI on the host machine at `http://127.0.0.1:9117/UI/Dashboard`, but all of Jackett's connections will go via the VPN.
388396
397+
#### Plex - port forwarding
398+
399+
Plex can be run and port forwarded (for Internet accessibility) with the following command and bash script.
400+
401+
Note this assumes a standard Arch Linux plex-media-server installation (i.e. where Plex uses its own `plex` user).
402+
403+
In `/home/plex/plex_launch.sh`:
404+
```bash
405+
#!/bin/bash
406+
# Plex config env vars
407+
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver/lib
408+
export PLEX_MEDIA_SERVER_HOME=/usr/lib/plexmediaserver
409+
export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plex
410+
export PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS=6
411+
export PLEX_MEDIA_SERVER_TMPDIR=/tmp
412+
export TMPDIR=/tmp
413+
414+
PLEX_LOCAL_PORT=32400 # Seems this is hardcoded in Plex
415+
# local address will only be accesible if running vopono with -o 32400
416+
echo "local Plex address: http://$VOPONO_NS_IP:$PLEX_LOCAL_PORT"
417+
# This assume using --port-forwarding or --custom-port-forwarding for ProtonVPN or PIA
418+
echo "remote Plex address: http://$(curl -4s ifconfig.co):$VOPONO_FORWARDED_PORT"
419+
# Here we redirect incoming connections on the forwarded to the port to the local Plex one (since we cannot change it! unlike transmission-gtk etc.)
420+
# Run this in background as it would block
421+
socat tcp-l:"$VOPONO_FORWARDED_PORT",fork,reuseaddr tcp:"$VOPONO_NS_IP":"$PLEX_LOCAL_PORT" &
422+
423+
/usr/lib/plexmediaserver/Plex\ Media\ Server
424+
# Kill socat background process on termination
425+
kill %1
426+
```
427+
428+
The `plex` user must have access to the above script, e.g.:
429+
```bash
430+
sudo chown -R plex /home/plex/
431+
sudo chmod 777 /home/plex/plex_launch.sh
432+
```
433+
434+
Launch vopono with the following command (e.g. here with a ProtonVPN custom Wireguard config):
435+
436+
```bash
437+
$ vopono exec --user plex --custom ~/Downloads/protonvpn-RO-9.conf --protocol wireguard --provider custom --custom-port-forwarding protonvpn -o 32400 /home/plex/plex_launch.sh
438+
```
439+
440+
Note the `-o 32400` is necessary to have local access to the Plex server from the host, which can be very useful for debugging.
441+
442+
389443
#### Proxy to host
390444
391445
By default, vopono runs a small TCP proxy to proxy the ports on your

src/args_config.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,26 @@ impl ArgsConfig {
113113
.ok()
114114
.and_then(|s| PathBuf::from_str(s.as_ref()).ok())
115115
});
116+
117+
// Note application cannot be defined in config file
118+
let application: String = shellexpand::full(&command.application)
119+
.map_err(|e| {
120+
anyhow!(
121+
"Shell expansion error for application: {:?}, error: {:?}",
122+
&command.application,
123+
e
124+
)
125+
})
126+
.map(|c| c.to_string())?;
116127
let custom_netns_name = command_else_config_option!(custom_netns_name, command, config);
117128
let open_hosts = command_else_config_option!(open_hosts, command, config);
118129
let hosts = command_else_config_option!(hosts, command, config);
119130
let open_ports = command_else_config_option!(open_ports, command, config);
120131
let forward = command_else_config_option!(forward, command, config);
132+
dbg!(&command.postup); // TODO
121133
let postup = command_else_config_option!(postup, command, config)
122134
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
123-
135+
dbg!(&postup);
124136
let predown = command_else_config_option!(predown, command, config)
125137
.and_then(|p| shellexpand::full(&p).ok().map(|s| s.into_owned()));
126138
let group = command_else_config_option!(group, command, config);
@@ -256,8 +268,7 @@ impl ArgsConfig {
256268
protocol,
257269
interface,
258270
server,
259-
// TODO: Allow application to be saved in config file? - breaking change to CLI interface
260-
application: command.application,
271+
application,
261272
user,
262273
group,
263274
working_directory,

0 commit comments

Comments
 (0)