Currently utilizing noVNC and x11vnc on a raspberry pi to provide remote support for device through the browser. Is it possible to specify somewhere in the docker-compose.yml or in the network settings of the device, to ONLY allow connections/traffic through the Public Device URL and not the IP address of the device?
In other words, I am looking for a way to only gain access to the device when using the public URL - I dont want anything exposed when the IP address of the device is entered into a browser on another device.
I was able to specify for noVNC to bind to the resin-vpn ip address. However, it appears as though this address is specified by DHCP. Is there any way to fix this IP address to be static?
@wwalker
getting a constant IP on the vpn is unlikely to work so the way to go, will be using iptables firewall rules inside the container to prevent access from interfaces other than the VPN.
The Balena superisor does the same sort of thing by setting rules as follows:
INPUT -p tcp --dport {port} -i {iface} -j ACCEPT
INPUT -p tcp --dport ${port} -j REJECT
Don’t hesitate to reach out to us if you need further support.
Thanks for the reply @shaunmulligan . I deleted some of my earlier rules to match those mention by you. For some reason this does not work with my device
root@c4773ae:~# iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION
-N DOCKER-USER
-A INPUT -i supervisor0 -p tcp -m tcp --dport 48484 -j ACCEPT
-A INPUT -i lo -p tcp -m tcp --dport 48484 -j ACCEPT
-A INPUT -i docker0 -p tcp -m tcp --dport 48484 -j ACCEPT
-A INPUT -i tun0 -p tcp -m tcp --dport 48484 -j ACCEPT
-A INPUT -i resin-vpn -p tcp -m tcp --dport 48484 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 48484 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -j DROP
-A INPUT -i wlan0 -p tcp -m tcp --dport 80 -j DROP
-A INPUT -i resin-vpn -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o balena0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o balena0 -j DOCKER
-A FORWARD -i balena0 ! -o balena0 -j ACCEPT
-A FORWARD -i balena0 -o balena0 -j ACCEPT
-A FORWARD -o supervisor0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o supervisor0 -j DOCKER
-A FORWARD -i supervisor0 ! -o supervisor0 -j ACCEPT
-A FORWARD -i supervisor0 -o supervisor0 -j ACCEPT
-A FORWARD -o br-dfd0deb2f977 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-dfd0deb2f977 -j DOCKER
-A FORWARD -i br-dfd0deb2f977 ! -o br-dfd0deb2f977 -j ACCEPT
-A FORWARD -i br-dfd0deb2f977 -o br-dfd0deb2f977 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i br-dfd0deb2f977 -o br-dfd0deb2f977 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION -i supervisor0 -o balena0 -j DROP
-A DOCKER-ISOLATION -i balena0 -o supervisor0 -j DROP
-A DOCKER-ISOLATION -i br-dfd0deb2f977 -o balena0 -j DROP
-A DOCKER-ISOLATION -i balena0 -o br-dfd0deb2f977 -j DROP
-A DOCKER-ISOLATION -i br-dfd0deb2f977 -o supervisor0 -j DROP
-A DOCKER-ISOLATION -i supervisor0 -o br-dfd0deb2f977 -j DROP
-A DOCKER-ISOLATION -j RETURN
-A DOCKER-USER -j RETURN
Here are my active rules:
root@c4773ae:~# iptables -vL
Chain INPUT (policy ACCEPT 471 packets, 51948 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- supervisor0 any anywhere anywhere tcp dpt:48484
127 8716 ACCEPT tcp -- lo any anywhere anywhere tcp dpt:48484
0 0 ACCEPT tcp -- docker0 any anywhere anywhere tcp dpt:48484
0 0 ACCEPT tcp -- tun0 any anywhere anywhere tcp dpt:48484
0 0 ACCEPT tcp -- resin-vpn any anywhere anywhere tcp dpt:48484
0 0 REJECT tcp -- any any anywhere anywhere tcp dpt:48484 reject-with icmp-port-unreachable
0 0 DROP tcp -- eth0 any anywhere anywhere tcp dpt:http
0 0 DROP tcp -- wlan0 any anywhere anywhere tcp dpt:http
0 0 ACCEPT tcp -- resin-vpn any anywhere anywhere tcp dpt:http
0 0 DROP tcp -- any any anywhere anywhere tcp dpt:http
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
7446 7999K DOCKER-USER all -- any any anywhere anywhere
7446 7999K DOCKER-ISOLATION all -- any any anywhere anywhere
0 0 ACCEPT all -- any balena0 anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- any balena0 anywhere anywhere
0 0 ACCEPT all -- balena0 !balena0 anywhere anywhere
0 0 ACCEPT all -- balena0 balena0 anywhere anywhere
0 0 ACCEPT all -- any supervisor0 anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- any supervisor0 anywhere anywhere
0 0 ACCEPT all -- supervisor0 !supervisor0 anywhere anywhere
0 0 ACCEPT all -- supervisor0 supervisor0 anywhere anywhere
3808 325K ACCEPT all -- any br-dfd0deb2f977 anywhere anywhere ctstate RELATED,ESTABLISHED
36 2160 DOCKER all -- any br-dfd0deb2f977 anywhere anywhere
3602 7672K ACCEPT all -- br-dfd0deb2f977 !br-dfd0deb2f977 anywhere anywhere
0 0 ACCEPT all -- br-dfd0deb2f977 br-dfd0deb2f977 anywhere anywhere
Chain OUTPUT (policy ACCEPT 518 packets, 59818 bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (3 references)
pkts bytes target prot opt in out source destination
36 2160 ACCEPT tcp -- !br-dfd0deb2f977 br-dfd0deb2f977 anywhere 172.18.0.2 tcp dpt:http
Chain DOCKER-ISOLATION (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- supervisor0 balena0 anywhere anywhere
0 0 DROP all -- balena0 supervisor0 anywhere anywhere
0 0 DROP all -- br-dfd0deb2f977 balena0 anywhere anywhere
0 0 DROP all -- balena0 br-dfd0deb2f977 anywhere anywhere
0 0 DROP all -- br-dfd0deb2f977 supervisor0 anywhere anywhere
0 0 DROP all -- supervisor0 br-dfd0deb2f977 anywhere anywhere
7446 7999K RETURN all -- any any anywhere anywhere
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
7446 7999K RETURN all -- any any anywhere anywhere
IP address of my device running balena
root@c4773ae:~# ip address show eth0 | grep "inet 192"
inet 192.168.1.161/24 brd 192.168.1.255 scope global dynamic eth0
root@c4773ae:~#
I can still access Node-RED from my laptop (192.168.1.110) as shown in the following screen shot:
I used incognito mode to ensure this was not a cached page.
Thanks @xandfury , could you also let us know what device-type and OS version you are running on. Also if you have a spare device lying around, perhaps you could try do the setup on a freshly provisioned device and see if that affects things (just to rule out some older changes in networking)
@shaunmulligan I mention device-type and OS version in a separate comment above Unfortunately I do not have a spare device with me. So can’t test this with a fresh install.
On a side-note, my iptable rules do not persist over reboot as well.
I currently have a single container setup. Not so long ago on the same device I had multiple containers. Is there any chance I can do this without actually ssh`ing onto the hostOS?
Also is it safe to assume that these rules would persist across reboot?
We currently don’t have a way to let the user apply iptables rules without ssh’ing and they will not be persistent after reboot.
What you can do in the context of a single container application is to add in your application the instructions to modify the rules. This way every time your application starts it will modify the rules.
Thanks @spanceac@wrboyce@shaunmulligan!
I did some digging and found a work-around for this. I am using NetworkManger to populate my iptable rules when the device is rebooted. Here is what I did:
Create a file /etc/NetworkManager/dispatcher.d/pre-up.d/iptables.sh with the following:
#!/bin/sh
LOGFILE=/var/log/iptables.log
IPTABLES_RESTORE=$(which iptables-restore)
if [ "$1" = lo ]; then
echo "$0: ignoring $1 for \`$2'" >> $LOGFILE
exit 0
fi
case "$2" in
pre-up)
echo "$0: restoring iptables rules for $1" >> $LOGFILE
$IPTABLES_RESTORE /etc/network/iptables.up.rules >> $LOGFILE 2>&1
;;
*)
echo "$0: nothing to do with $1 for \`$2'" >> $LOGFILE
;;
esac
exit 0
Give the permissions to the script with chmod a+x /etc/NetworkManager/dispatcher.d/pre-up.d/iptables.sh
@xandfury it looks like you are modifying the NetworkManager dispatcher configuration on the host OS through SSH, right? This is not safe for production environment as any host OS update will wipe out that modification. Is there any issue with modifying the iptable rules at the very beginning of the start shell script of your container? This way whenever your application starts afterwards those will be already applied.
it looks like you are modifying the NetworkManager dispatcher configuration on the host OS through SSH, right?
Correct!
Is there any issue with modifying the iptable rules at the very beginning of the start shell script of your container? This way whenever your application starts afterwards those will be already applied.
That honestly would’ve been the best solution. The problem with that is resin-vpn interface is not available on my container
@xandfury you mentioned you are using a single-container application, so the resin-vpn interface should be available, at least I can see it on a device I have here. If you are using a multi-container setup, then you will need to enable host networking and privileged mode for the particular container. Please let me know if what I say does not work for any reason.
Ah… It was multi-container initially. I removed all services except one - so now single container.
Just made changes to the docker-compose. I see the interfaces now
Tbh making changes to NetworkManager dispatcher config felt a bit too hackish. This should definitely solve my issue.