Combine someone repeated sections, don't teach network.scgi.open_port in actual tutorials, as it is less secure.

Matthew Strasiotto
2021-07-05 09:40:39 +10:00
parent 5b5f57cf15
commit b194f527d0
+79 -56
@@ -6,34 +6,49 @@
* Use domain sockets, and only mention TCP in a warning
* Take out all the "you could" stuff that only confuses people (less options is more)
## Security concerns regarding exposing the `xmlrpc` API
Before continuing, it's worth mentioning that `rtorrent` methods are very flexible, and powerful, and can be used to execute arbitrary commands on your system. Think of exposing access to your `rtorrent` API as equivalent to exposing access to your system's shell.
You **do not** want your rtorrent XMLRPC api to fall into the wrong hands.
There are two ways to expose the xmlrpc endpoint for `rtorrent`:
You can:
✔️ Configure rtorrent to expose the endpoint to a local unix domain socket, for example `~/.local/rtorrent.sock`.
* You will then use a reverse proxy to publish this socket under some host, __with some authentication mechanism set up__.
* ✔️ This is considered **more secure** as local unix domain sockets can be assigned unix file read/write modes that can control which users on the system can & cannot access the API.
❌ Configure rtorrent to expose this socket on some address + port, eg `localhost:5000`/`127.0.0.1:5000`
* ⚠️ You *must never* publish this on any address besides `localhost` (`127.0.0.1`)
* ⚠️ Even if you do bind this to localhost, publishing directly to a port is still **less secure** than publishing to a unix domain socket & proxying that
* Directly publishing to localhost is less secure because *any user* on the localhost can access `localhost:5000` and use the API, thereby getting access to everything that the user that runs `rtorrent` has access to.
* ❌ In addition, you will most likely need to configure a reverse proxy to help publish your endpoint, so the convenience is not great.
<small>
This warning being said- Any time in this guide that you see `rtorrent` configured to publish to a local unix socket, and a reverse proxy configured to forward that, a similar effect could be achieved by directly publishing to a port, and the reverse proxy exposing that endpoint.
In `rtorrent.rc`, the **deprecated** method `network.scgi.open_port = 127.0.0.1:5000` may be used to publish directly to a port.
</small>
Without much further ado
## Configuring rtorrent and your webserver
What you need:
* http://python.ca/scgi/ for Apache 2.2, mod_proxy_scgi enabled for Apache 2.4, Lighttpd should have this built-in.
* rtorrent compiled / configured with the `--with-xmlrpc-c` flag
* `scgi` for your reverse proxy:
* http://python.ca/scgi/ for Apache 2.2,
* mod_proxy_scgi enabled for Apache 2.4,
* Lighttpd should have this built-in,
* recent versions of nginx have this built in.
* http://xmlrpc-c.sourceforge.net/ 1.00 or later, 1.07 or later for 64bit integer support.
Configure rtorrent with the `--with-xmlrpc-c` flag. Then add appropriate configuration, according used web-server.
### rtorrent configuration (rtorrent.rc)
### Apache
**httpd.conf (2.2)**:
```ini
SCGIMount /RPC2 127.0.0.1:5000
```
**httpd.conf (2.4)**:
```ini
ProxyPass /RPC2 scgi://127.0.0.1:5000
```
**rtorrent.rc**:
```ini
network.scgi.open_port = 127.0.0.1:5000
```
### Lighttpd:
**rtorrent.rc**:
```ini
network.scgi.open_local = /home/user/rtorrent/rpc.socket
@@ -43,6 +58,24 @@ network.scgi.open_local = /home/user/rtorrent/rpc.socket
schedule2 = scgi_permission,0,0,"execute.nothrow=chmod,\"g+w,o=\",/home/user/rtorrent/rpc.socket"
```
### Apache
**httpd.conf (2.2)**:
```ini
SCGIMount /RPC2 socket_path <TODO: Check syntax to mount unix sockets>
```
**httpd.conf (2.4)**:
```ini
ProxyPass /RPC2 scgi://socket_path <TODO: Check syntax to mount unix sockets>
```
**rtorrent.rc**:
```ini
network.scgi.open_port = 127.0.0.1:5000
```
### Lighttpd:
**lighttpd.conf**:
```ini
server.modules += ( "mod_scgi" )
@@ -54,56 +87,46 @@ scgi.server = (
"check-local" => "disable",
"disable-time" => 0, # don't disable scgi if connection fails
)
# YOU MUST ADD SOME KIND OF AUTH
)
)
```
### Nginx:
**rtorrent.rc**:
```ini
network.scgi.open_port = 127.0.0.1:5000
```
*Recent version of nginx support scgi by default*
**nginx.conf**:
***INSECURE CONFIG, DO NOT USE!***
```
location /RPC2 {
scgi_pass 127.0.0.1:5000;
include scgi_vars;
scgi_var SCRIPT_NAME /RPC2;
}
```
or (on ubuntu server 14.04)
```
http {
server {
listen 0.0.0.0:8008;
server_name ngnix-rtorrent;
access_log /var/log/nginx/rtorrent.access_log;
error_log /var/log/nginx/rtorrent.error_log;
location /RPC2 {
scgi_pass 127.0.0.1:5000;
include scgi_params;
}
}
```conf
# This webserver is actually in a container that only publishes 8080 (container) -> localhost:8080 (host)
server {
listen 0.0.0.0:8080;
error_log ${CONFIG_DIR}/nginx/nginx.error.log;
access_log ${CONFIG_DIR}/nginx/access.log main;
auth_basic "Restricted";
# Users must log on with matching credentials
auth_basic_user_file ${NGINX_BASIC_AUTH_FILE};
location /RPC2 {
include scgi_params;
scgi_pass unix:${RTORRENT_SOCKET_PATH};
}
}
```
Do not forget, that on http://localhost:8008/RPC2 you will not see anything (through in rtorrent.error_log you will see something as `upstream prematurely closed connection while reading response header from upstream, client: 192.168.93.104, server: ngnix-rtorrent, request: "GET /RPC2 HTTP/1.1", upstream: "scgi://127.0.0.1:5000", host: "192.168.93.242:8008"`. It is xmlrpc, not web service. You can test it by xmlrpc (see later))
**SECURITY NOTE**: use some basic auth, client certificate, SSO or any authentication method. Exemple for basic auth:
**SECURITY NOTE**:
```
location /RPC2 {
auth_basic "Restricted area";
auth_basic_user_file /etc/nginx/auth/seedbox_auth;
scgi_pass 127.0.0.1:5000;
include scgi_params;
}
```
⚠️ use some basic auth, client certificate, SSO or any authentication method. Example for basic auth given above.
⚠️ This config should also sit behind a TLS terminating proxy, so that user credentials are not sent unencrypted.
* To put it another way, __use `https`__
It's worth mentioning that most clients do not provide support for authentication mechanisms besides basic auth, such as client certificates or SSO.
## Other notes
@@ -113,7 +136,7 @@ If any of your downloads have non-ascii characters in the filenames, you must al
encoding.add = UTF-8
```
The web server will now route xmlrpc requests to rtorrent, which is listening only on connections from the local machine or on the local socket file. Also make sure the /RPC2 location is properly protected, and also name it differently to evade attackers probing for vulnerabilities.
The web server will now route xmlrpc requests to rtorrent, which is listening only on connections from the local machine or on the local socket file. Also make sure the /RPC2 location is properly protected, (as in, has *at least* basic auth enabled, and is secured by SSL) and ~also name it differently to evade attackers probing for vulnerabilities~ (security through obscurity is not security, though this may reduce frequency of attempted exploits)
:bangbang: **Never** bind the SCGI port to anything *but* 127.0.0.1. Anyone who can send rtorrent xmlrpc commands does have the ability to execute code with the privileges of the user running rtorrent. If you want to be more secure on principle, use UNIX domain sockets instead of TCP ports (see below).