Docker-transmission-openvpn: Access WebUI from WAN?

Created on 15 Apr 2018  Â·  19Comments  Â·  Source: haugene/docker-transmission-openvpn

I'd very much like to be able to access Transmission's web UI from outside of my LAN. That way, if I'm not home, I can start a torrent remotely and have it done when I get home. I'm honestly not sure where to start.

Most helpful comment

Wish I had known that before going through all this. Ah, well. @auanasgheps, your technique worked.

#!/bin/bash
docker kill transmission-openvpn 2> /dev/null
docker rm transmission-openvpn 2> /dev/null
docker pull haugene/transmission-openvpn
docker run \
        --cap-add=NET_ADMIN \
        --device=/dev/net/tun -d \
        --dns 8.8.8.8 \
        --ip 172.18.0.2 \
        --name transmission-openvpn \
        --net newbridge \
        -e "LOCAL_NETWORK=10.0.1.0/24" \
        -e "OPENVPN_CONFIG=[redacted]" \
        -e "OPENVPN_PASSWORD=[redacted]" \
        -e "OPENVPN_PROVIDER=[redacted]" \
        -e "OPENVPN_USERNAME=[redacted]" \
        -e "PGID=$(id -g)" \
        -e "PUID=$(id -u)" \
        -e "TRANSMISSION_HOME=/config/transmission" \
        -e "TRANSMISSION_INCOMPLETE_DIR=/data/incomplete" \
        -e "TRANSMISSION_INCOMPLETE_DIR_ENABLED=true" \
        -e "TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true" \
        -e "TRANSMISSION_RPC_BIND_ADDRESS=*.*.*.*" \
        -e "TRANSMISSION_RPC_ENABLED=true" \
        -e "TRANSMISSION_RPC_PASSWORD=[redacted]" \
        -e "TRANSMISSION_RPC_USERNAME=[redacted]" \
        -e "TRANSMISSION_SPEED_LIMIT_UP=150" \
        -e "TRANSMISSION_SPEED_LIMIT_UP_ENABLED=true" \
        -p 9091:9091 \
        -v [redacted]:/config/ \
        -v [redacted]:/data/ \
        haugene/transmission-openvpn 1> /dev/null

docker kill nginx 2> /dev/null
docker rm nginx 2> /dev/null
docker pull nginx
docker run \
        --dns 8.8.8.8 \
        --ip 172.18.0.3 \
        --name=nginx \
        --net newbridge \
        --restart unless-stopped \
        -e "PGID=$(id -g)" \
        -e "PUID=$(id -u)" \
        -p 8100:8100 \
        -v /etc/localtime:/etc/localtime:ro \
        -v [redacted]:/etc/nginx/ \
        -v [redacted]:/usr/share/nginx/html:ro \
        -v [redacted]:/etc/nginx/certs:ro \
        nginx 1> /dev/null &

And my nginx config:

events {
        worker_connections 1024;
}

http {

        server {
                listen 8100 default_server;
                server_name hostname;

                client_max_body_size 0;
                gzip off;

                proxy_http_version 1.1;

### Transmission Web-UI config
                location /{
                        proxy_pass http://172.18.0.2:9091/;
                        add_header X-Frame-Options SAMEORIGIN;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                }
        }
}

All posted for posterity, or for if someone runs into the same issue I did and wants to solve it this way.

Thank you very much for your assistance.

All 19 comments

The simplest way this can be achieved is by opening port 9091 (or whatever port you access Transmission on) on your router. You will then be able to navigate to your WAN ip address and port to access your transmission (e.g. http://2.456.789.123:9091).
However, I wouldn't recommend doing this. My preferred way would be to run a VPN server. You would then be able to connect to your VPN server (encrypted) and access everything like you would normally be able to on your LAN network.

I use a nginx container running in the same docker network. It allows to proxy the connection from the port I choose to the WebUI of Transmission. I also use it for other containers.
A mayor advantage over exposing Transmission webUI is that you can enable (and force) SSL connections, which is something that I've obviously done.
I can provide more details if it's something you're looking into.

That's just the thing, @tomhumphrey, I do have the port forwarded. My router is a custom Linux machine with nothing exciting on it but iptables and dnsmasq. I've forwarded the port in precisely the same way I forwarded other ports which do work, but this one doesn't.

The following lines have been trimmed.

-A fw-open -d 10.0.1.2/32 -p tcp -m tcp --dport 9091 -j ACCEPT
-A PREROUTING -i eth1 -p tcp -m tcp --dport 9091 -j DNAT --to-destination 10.0.1.2

From within the LAN:
tralce@eli ~ ➜ % nmap 10.0.1.2
22/tcp open ssh
9091/tcp open xmltec-xmlmail

From a host outside of this network:

tralce@caroline ~ ➜ % nmap [my ip]
22/tcp open ssh
9091/tcp filtered xmltec-xmlmail

The strangest thing is that port 22 which is forwarded in exactly the same way to exactly the same host does work. Any thoughts? I'm fairly sure it's not to do with my port forwards, since any other port I choose to forward in this manner works fine, and only this one doesn't. Is the container rejecting (or is Docker itself rejecting) connections originating from IPs outside of 10.0.1.0/32? If so, how would I go about correcting that?

@auanasgheps For the moment I'm less worried about security and more worried about being able to connect from outside at all. One step at a time.

Are you forwarding the port to the host or the container?
In my case the container is running in a docker network, so I have set up forwarding to the host (my NAS server).

I would suggest to create a new container using a plain image of Transmission (no VPN) and see if forwarding goes trough, it will then be clear if the problem is your router or not.

@auanasgheps To the host. The host machine's IP on my LAN is 10.0.1.2. I honestly don't have a lot of Docker experience, so I didn't know there was any other way. I just was accessing the Web UI by browsing to 10.0.1.2:9091 so it stood to reason that forwarding a port there would work. Is this not so?

My docker LAN is 10.0.x.x so that's why I asked :)
Yes it's correct, port forwarding must be done towards the host. As long as you can browse hostIP:9091 in your LAN you should be able to do so from WAN using port forwarding.

However there could be other issues that's why I suggested to use a plain Transmission container.
Stop the Transmission VPN container, spin up this container on port 9091 and try again.

@auanasgheps That does work. So this means it's something to do with this container. Here's my script that starts it. Thoughts?

tralce@gman ~ ➜ % cat Documents/Scripts/starttransmission-docker.sh
#!/bin/bash
docker kill transmission-openvpn &> /dev/null
docker rm transmission-openvpn &> /dev/null
docker pull haugene/transmission-openvpn
docker run --name transmission-openvpn \
        --cap-add=NET_ADMIN --device=/dev/net/tun -d \
        -v redacted:/data/ \
        -v redacted:/config/ \
        -e "LOCAL_NETWORK=10.0.1.0/24" \
        -p 9091:9091 \
        -e "PUID=$(id -u)" \
        -e "PGID=$(id -g)" \
        -e "OPENVPN_PROVIDER=redacted" \
        -e "OPENVPN_CONFIG=redacted" \
        -e "OPENVPN_USERNAME=redacted" \
        -e "OPENVPN_PASSWORD=redacted" \
        -e "TRANSMISSION_HOME=/config/transmission" \
        -e "TRANSMISSION_INCOMPLETE_DIR=/data/incomplete" \
        -e "TRANSMISSION_INCOMPLETE_DIR_ENABLED=true" \
        -e "TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true" \
        -e "TRANSMISSION_RPC_BIND_ADDRESS=0.0.0.0" \
        -e "TRANSMISSION_RPC_ENABLED=true" \
        -e "TRANSMISSION_RPC_PASSWORD=redacted" \
        -e "TRANSMISSION_RPC_USERNAME=redacted" \
        -e "TRANSMISSION_SPEED_LIMIT_UP=150" \
        -e "TRANSMISSION_SPEED_LIMIT_UP_ENABLED=true" \
        -e "WEBPROXY_ENABLED=true" \
        -e "WEBPROXY_PORT=8888" \
        --dns 8.8.8.8 haugene/transmission-openvpn

I haven't specified LOCAL_NETWORK variable at all and works perfectly. Try without that.
EDIT: Disable WebProxy as well, remove both entries

@auanasgheps The plot thickens. Without those lines, not only can I not connect remotely, I can now only connect on the host machine using 127.0.0.1.

Ah, I see.

Re-add LOCAL_NETWORK variable, remove all TRANSMISSION_RPC variables and try again. I know it's insecure without auth but it's just for the sake of the test.

Same thing again. Port it filtered, times out when I attempt to connect with curl.

Just bear in mind you must not specify TRANSMISSION_RPC_BIND_ADDRESS
This value is pushed by the container every tim the VPN is set, and will result in the internal LAN IP address of your VPN.

Aside than that I can't find other issues.
At this point you could use a nginx container as I stated earlier

If I don't specify TRANSMISSION_RPC_BIND_ADDRESS, it seems to default to 127.0.0.1 which is actually more useless than what it's already doing.

Alright, I guess I'll be forced to try your nginx technique at this point. I just didn't really want to unnecessarily complicate this is all. Got a guide? I don't know the first thing about using nginx.

OK now I have the server in front of me and I can doublecheck things.
I have confused TRANSMISSION_RPC_BIND_ADDRESS with TRANSMISSION_BIND_ADDRESS_IPV4. I was referring to the latter, so sorry about the confusion.

This is my settings.json file. I have not specified any of the following settings, they are all pushed by the template of the container, which contains defaults for every Transmission settings.
So if you don't specify any of the below settings, what do you get?

    "rpc-authentication-required": false,
    "rpc-bind-address": "0.0.0.0",
    "rpc-enabled": true,
    "rpc-host-whitelist": "",
    "rpc-host-whitelist-enabled": false,
    "rpc-password": "redacted",
    "rpc-port": 9091,
    "rpc-url": "/transmission/",
    "rpc-username": "username",
    "rpc-whitelist": "127.0.0.1",
    "rpc-whitelist-enabled": false,

If you mean not specifying any of those settings using -e VAR=setting in my script, nothing is different at all. I tried adjusting the settings.json file from the dir that is bound to /config in the container to match yours and I'm actually still in the same boat. The port is still coming up as filtered from a remote host.

If you mean not specifying any of those settings using -e VAR=setting in my script,

Exactly.

I can't to help further in Transmission troubleshooting, but I can certainly provide help with nginx.

This is the docker run command

docker run -d \
--name=nginx \
--restart unless-stopped \
-v path/to/confing/file:/etc/nginx/ \
-v path/to/ssl/certs:/etc/nginx/certs:ro \
-v path/to/html/content:/usr/share/nginx/html:ro \
-v /etc/localtime:/etc/localtime:ro \
-p 8080:8080 \
-e PUID= UID \
-e PGID=GID \
nginx

You will need to provide a nginx config file and store it in the first mounted folder. Here's mine adapted for your needs.

Note that in TRANSMISSIONIPADDRESS I enter the docker LAN IP address. In my docker network every container has a static IP.
Please note I haven't tested this config, I hope I haven't made any errors!

events {
  worker_connections 1024;
}

http {

  server {
      listen 8080 default_server;
    server_name hostname; #I use enter my external DNS name in hostname, but a local hostname can be used too

    client_max_body_size 0;
    gzip off;

    proxy_http_version 1.1;

### Transmission Web-UI config
    location /{
    proxy_pass http://TRANSMISSIONIPADDRESS:9091/;
    add_header X-Frame-Options SAMEORIGIN;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
}
}

There is a much easier way of doing this. If you don't care about SSL and other things, read here
https://github.com/haugene/docker-transmission-openvpn#access-the-webui

Haugene made a ready to use nginx container

Wish I had known that before going through all this. Ah, well. @auanasgheps, your technique worked.

#!/bin/bash
docker kill transmission-openvpn 2> /dev/null
docker rm transmission-openvpn 2> /dev/null
docker pull haugene/transmission-openvpn
docker run \
        --cap-add=NET_ADMIN \
        --device=/dev/net/tun -d \
        --dns 8.8.8.8 \
        --ip 172.18.0.2 \
        --name transmission-openvpn \
        --net newbridge \
        -e "LOCAL_NETWORK=10.0.1.0/24" \
        -e "OPENVPN_CONFIG=[redacted]" \
        -e "OPENVPN_PASSWORD=[redacted]" \
        -e "OPENVPN_PROVIDER=[redacted]" \
        -e "OPENVPN_USERNAME=[redacted]" \
        -e "PGID=$(id -g)" \
        -e "PUID=$(id -u)" \
        -e "TRANSMISSION_HOME=/config/transmission" \
        -e "TRANSMISSION_INCOMPLETE_DIR=/data/incomplete" \
        -e "TRANSMISSION_INCOMPLETE_DIR_ENABLED=true" \
        -e "TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true" \
        -e "TRANSMISSION_RPC_BIND_ADDRESS=*.*.*.*" \
        -e "TRANSMISSION_RPC_ENABLED=true" \
        -e "TRANSMISSION_RPC_PASSWORD=[redacted]" \
        -e "TRANSMISSION_RPC_USERNAME=[redacted]" \
        -e "TRANSMISSION_SPEED_LIMIT_UP=150" \
        -e "TRANSMISSION_SPEED_LIMIT_UP_ENABLED=true" \
        -p 9091:9091 \
        -v [redacted]:/config/ \
        -v [redacted]:/data/ \
        haugene/transmission-openvpn 1> /dev/null

docker kill nginx 2> /dev/null
docker rm nginx 2> /dev/null
docker pull nginx
docker run \
        --dns 8.8.8.8 \
        --ip 172.18.0.3 \
        --name=nginx \
        --net newbridge \
        --restart unless-stopped \
        -e "PGID=$(id -g)" \
        -e "PUID=$(id -u)" \
        -p 8100:8100 \
        -v /etc/localtime:/etc/localtime:ro \
        -v [redacted]:/etc/nginx/ \
        -v [redacted]:/usr/share/nginx/html:ro \
        -v [redacted]:/etc/nginx/certs:ro \
        nginx 1> /dev/null &

And my nginx config:

events {
        worker_connections 1024;
}

http {

        server {
                listen 8100 default_server;
                server_name hostname;

                client_max_body_size 0;
                gzip off;

                proxy_http_version 1.1;

### Transmission Web-UI config
                location /{
                        proxy_pass http://172.18.0.2:9091/;
                        add_header X-Frame-Options SAMEORIGIN;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                }
        }
}

All posted for posterity, or for if someone runs into the same issue I did and wants to solve it this way.

Thank you very much for your assistance.

Glad you got it working @tralce. As for the networking and port forwarding part, I've described it a bit in #354. When you forwarded the port from your router, your packages got to the container. It's the response that was the issue (I guess :)).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

coulterj picture coulterj  Â·  4Comments

stefanahman picture stefanahman  Â·  4Comments

jsloan117 picture jsloan117  Â·  3Comments

lorgio picture lorgio  Â·  4Comments

ovizii picture ovizii  Â·  3Comments