0

Background: I'm configuring Transmission (v2.93) and OpenVPN (v2.4.6) in a jail (a FreeNAS 11.1 plugin jail) and want to add an --up script to OpenVPN which will request Transmission to change its listening port (using transmission-remote program).

My openvpn.conf contains the following (among others):

verb 4
script-security 2
up /usr/local/etc/openvpn/set_port.sh
up-restart ;only to make the up script be executed on restarts
           ;but disabling this changes nothing

and the set_port.sh script contains (a minimal script that still reproduces the behavior):

#!/usr/local/bin/bash
/usr/local/bin/transmission-remote --auth rpc_user:rpc_pass -p 6666 2>&1 > output.txt
echo 'the script itself runs: '$(pwd) $(whoami) > status.txt

The script has all permissions (777) and the binary (transmission-remote) has all the permissions. I am aware the path to binary is actually a soft link, so I replaced it with the actual path (/usr/pbi/transmission-amd64/.sbin/transmission-remote) but the behavior I observe is the same.

Problem: when I start OpenVPN (service openvpn start), the script itself is executed, but the actual command fails mysteriously: the port is not being assigned (verified by looking through Transmission Remote GUI and the command generates empty output.
Contents of the debug files are as follows:
output.txt is empty (with and without stderr redirection)
status.txt says as expected: the script itself runs: /usr/local/etc/openvpn root.

However, when I run this script manually (./set_port.sh), said command completes successfully: output.txt will say localhost:9091/transmission/rpc/ responded: "success" and the port will be changed.

What am I missing?

Similar to this question, except I am not getting any "permission denied" messages - it seems like the command is not even executed (if I echo $(<that command>) > file.txt, I get an empty file).
This one is also somewhat related, but the OP is asking about --client-connect and eventually solves the issue by writing full paths to the programs they want to run - this did not help in my case (but if I echo $(ls /usr/local/bin) > log.txt, the list of binaries is correct).

Update per @roaima's request. I changed the set_port.sh to the following:

#!/usr/local/bin/bash
exec >debug.txt 2>&1
set -x
echo script is running
/usr/pbi/transmission-amd64/.sbin/transmission-remote  --auth rpc_user:rpc_pass -p 6666 2>&1 > output.txt

then rinsed and repeated. The debug.txt file contained these lines:

+ echo script is running
script is running
+ /usr/pbi/transmission-amd64/.sbin/transmission-remote --auth rpc_user:rpc_pass -p 12345
/usr/local/etc/openvpn/test.sh: line 5:  6795 Segmentation fault      /usr/pbi/transmission-amd64/.sbin/transmission-remote --auth rpc_user:rpc_pass -p 12345 2>&1 > output.txt
4
  • Does the output.txt file get created, or did you previously create it before the script ran? What directory is the script running from (can you use absolute paths eg /tmp/output.txt)? What if you send stderr to the file too (/path/to/command >/tmp/output.txt 2>&1)? – roaima Jun 2 '18 at 8:13
  • Every time I restart the service, I also run a cleaning script to make sure those files (output.txt, status.txt) don't exist. And every time they are created: output is empty, status correctly reporting the user is root and the directory called from ($(pwd)) is exactly where the set_port.sh is. Redirecting stderr changes nothing. I updated the original post with this information. – Przemek D Jun 2 '18 at 13:20
  • Please insert these commands as the second, third and fourth lines of your script: exec >debug.txt 2>&1 and set -x and echo script is running. Put the contents of debug.txt into your question. – roaima Jun 2 '18 at 13:25
  • Fixed. I misunderstood you initially, now did what you requested. It revealed that I'm getting a segfault at the call to the binary! But why would it occur only when calling the script from OpenVPN? If I run manually, no such thing occurs. – Przemek D Jun 2 '18 at 13:52
1

Looking at the line

/usr/local/etc/openvpn/test.sh: line 5:  6795 Segmentation fault      /usr/pbi/transmission-amd64/.sbin/transmission-remote --auth rpc_user:rpc_pass -p 12345 2>&1 > output.txt

It looks like your executables have got mismatched libraries. Please recheck how you've built your chroot. (I haven't used FreeBSD for years and years so I can't give you pointers on how to do that, sorry.)

3
  • I'm not running chroot - at least I did not configure anything like that. The whole setup is running in a jail, which to my understanding is not the same. I'll try to research the libraries thing and see what I can dig up. – Przemek D Jun 2 '18 at 21:00
  • ldd says that transmission-remote only requires libc.so.7. Now I see that the file that resides within my jail's /lib/ is different to the one that lies in my main root (1744304 vs 1671232 bytes). Could this be of any significance? – Przemek D Jun 2 '18 at 22:10
  • @PrzemekD Yes definitely – roaima Jun 2 '18 at 22:23
0

I have no idea about the library mismatch that is going on here, especially that it all happens in a FreeNAS "plugin jail" and I don't know how it is configured. However, I have managed to work around the issue in order to achieve the goal of having OpenVPN configure Transmission at route-up.
Note: the following answer does NOT solve the segmentation fault issue, so I am not going to mark it as accepted.

The solution is based on the following observation: while transmission-remote segfaulted if called by OpenVPN, it ran perfectly fine if cron called it instead:

  1. Leave openvpn.conf as is.

  2. In set_port.sh, instead of calling transmission-remote, store the port number in a file - for example like this: echo $port > $path/port-id (from here on I will assume variable path leads to the folder where we store the scripts etc.)

  3. Make a new script, let's call it actually_set.sh, with the following:

#!/usr/local/bin/bash
if [ -f $path/port-id ]; then
  port=$(cat $path/port-id)
  rm $path/port-id
  transmission-remote -n 'rpc_user:rpc_pass' -p $port
fi
  1. Set cron to call the above script every minute. I put the following in my crontab:
    * * * * * /usr/local/etc/openvpn/ports/tp_setter.sh
-1

If you set your verb level to 3-4, you probably should see warnings about scripts not being run. By default, OpenVPN 2.2+ only calls certain built-ins. You need to relax this using script-security:

--script-security level

This directive offers policy-level control over OpenVPN's usage of external programs and scripts. Lower level values are more restrictive, higher values are more permissive.

Settings for level:

0 -- Strictly no calling of external programs.
1 -- (Default) Only call built-in executables such as ifconfig, ip, route, or netsh.
2 -- Allow calling of built-in executables and user-defined scripts.
3 -- Allow passwords to be passed to scripts via environmental variables (potentially unsafe).

You need to make sure that you have script-security set to 2 or 3 (2 if you don't need to send passwords to the script, 3 otherwise.)

4
  • I am already running script-security 2 - the script wouldn't be launched without it. The problem is that it launches but ignores this particular command. Setting verb 4 shows nothing unusual: tun device is opened, ifconfig sets something up, then my script is executed, then some routes are added and initialization sequence completes. My script does run, as confirmed by echoing from within it - but whenever I make a call to transmission-remote, it is ignored. – Przemek D Jun 2 '18 at 1:10
  • As it's running in a jail. the only other thing I can think of is that possibly access to localhost or some file is being blocked. Do you get any error messages if you redirect both standard output and error (i.e. transmission-remote ... >messages.txt 2>&1)? – ErikF Jun 2 '18 at 1:44
  • The output is empty even with 2>&1 - it is as if there was no such binary file. I tried executing some non-existent binary and the result was the same. Except that if I ls, said binary exists. (I'll update the question to contain this additional info.) – Przemek D Jun 2 '18 at 2:02
  • Very strange. The only other thing I can think of is to make sure that all the shared libraries (.so) are accessible if transmission-remote isn't statically linked. I would have thought that missing libraries would be reported, however. – ErikF Jun 2 '18 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.