Internet kill switch (for both wireless & wired devices)

Most routers with custom firmware (Tomato, DD-WRT, OpenWRT, etc) are likely allowing IPTABLES changes. Devices (both wireless and wired) can be permitted, per MAC or per IP, to connect to LAN but prevented from accessing Internet by modifying FORWARD chain.

This can come handy for keeping kids off internet (at least before the age of 5; afterwards they will likely be smarter than you) or keeping on LAN access only rogue devices that are home calling, only allow a device to connect to internet in order to upgrade firmware, etc.

*Router used below is an Asus running Merlin firmware (https://github.com/RMerl/asuswrt-merlin) and some of the specific commands could be different for other brands.

I. On HA host: set login without password and create switch that will kill internet for chosen device

1. Generate keys (take notice on folder used for storing)

1a. If running Hassio, create folder /config/.ssh if it doesn’t exist in order to preserve keys after reboot (/root/.ssh gets cleared at boot in my case although it seems to be solved a long time ago https://github.com/hassio-addons/addon-ssh/issues/3).

user@hass:~$ mkdir /config/.ssh

user@hass:~$ ssh-keygen -t rsa

1b. On Hassio change destination to /config/.ssh/id_rsa instead of /root/.ssh/id_rsa

Don’t set a passphrase (press Enter twice)

2. Create switch configuration

switch:
  - platform: command_line
    switches:
      control_internet_host_a:
        command_on: ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa [email protected] sh /jffs/scripts/block_host_a.sh
        command_off: ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa [email protected] sh /jffs/scripts/allow_host_a.sh

Note: on Hassio use:

        command_on: ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /config/.ssh/id_rsa [email protected] sh /jffs/scripts/block_host_a.sh
        command_off: ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /config/.ssh/id_rsa [email protected] sh /jffs/scripts/allow_host_a.sh

3. Connect to router at least once from HA machine (most common users are admin or root) and input password:

user@hass:~$ ssh [email protected]
[email protected]'s password:

4. Copy public key to router’s authorized keys (change source of /root/.ssh/id_rsa.pub to /config/.ssh/id_rsa.pub if set different in step 1)

user@hass:~$ cat /root/.ssh/id_rsa.pub | ssh [email protected] 'cat >> .ssh/authorized_keys'
[email protected]'s password:

Connecting again from HA host to router (user@hass:~$ ssh [email protected]) should not require password anymore.

II. On the router: create scripts needed for blocking/allowing internet
*Asus router is holding custom scripts in folder /jffs/scripts (possibly different on other brands). I’ve used post-mount instead of earlier time in boot below as I’m running adblocker by loading a list of hosts and sometimes not all hosts are updated.

A. Create folder to store keys (probably already exists)

admin@router:/# mkdir -p .ssh

B. Create block host script

admin@router:/# nano /jffs/scripts/block_host_a.sh

#!/bin/sh

iptables -I FORWARD -i br0 -m mac --mac-source 00:00:00:00:00:01 -j DROP

ctrl+x to save

C. Create allow host script

admin@router:/# nano /jffs/scripts/allow_host_a.sh

#!/bin/sh

iptables -D FORWARD -i br0 -m mac --mac-source 00:00:00:00:00:01 -j DROP

D. Make scripts executable

admin@router:/# chmod a+rx /jffs/scripts/block_host_a.sh
admin@router:/# chmod a+rx /jffs/scripts/allow_host_a.sh

E. Choose default start behaviour
Case only wanting to run the block upon request, the above config is sufficient.

E2. Otherwise, in order to block host at router boot, add the content of the block host script to post-mount (or create the file if it doesn’t exist):

admin@router:/# nano /jffs/scripts/post-mount

iptables -I FORWARD -i br0 -m mac --mac-source 00:00:00:00:00:01 -j DROP

(make sure post-mount starts with #!/bin/sh)

E3. In order to delete IPTABLES blocking rule(s) restart firewall or set a script on the router accessible from HA.

admin@router:/# nano /jffs/scripts/temporary_reset_blocking.sh

#!/bin/sh

service restart_firewall

set script as executable:

admin@router:/# chmod a+rx /jffs/scripts/temporary_reset_blocking.sh

Once the router is rebooted, the hosts included in post-mount are prevented from accessing Internet. Individual hosts can then be allowed by running allow_host_a.sh or all in one sitting by running temporary_reset_blocking.sh (hosts will be blocked again once router is rebooted or post-mount executed).

4 Likes

Hi, Perhaps you can help: tried to start Clamav jail on Freenas by adding connection without password (like you did) in order to scan files but cannot figure where to start aa there is no gui for the jail

Hi

I’ll look into it (does sound interesting :wink: )

Try this: first you need to mount the dataset that you want to scan under the jail. Shutdown jail, on mount points mount the dataset from FreeNAS host for which you have access to the jail’s /mnt folder (in jail it should be something like /mnt/dataset_name/iocage/jails/jail_name/root/mnt)

Enable ssh in the jail (Shell) by adding sshd_enable="YES" to /etc/rc.conf (nano is not installed by default in jail, however vi can be used)
vi /etc/rc.conf

Allow root login:
vi /etc/ssh/sshd_config and uncomment

PermitRootLogin yes
PasswordAuthentication yes

Change root password

passwd root

Create file for storing keys:

vi .ssh/authorized_keys

Restart jail

On HA (similar to the initial post)

Add key to jail:
cat /root/.ssh/id_rsa.pub | ssh [email protected] 'cat >> .ssh/authorized_keys'

Set the Clamav scan as script (easier than a switch/input_boolean) to be able to run it on demand:
clamdscan /mnt/*

Thanks, it worked (sort of; I can connect to the jail from Hassio and launch the scan but the files are not accessible for clamav).

What am I doing wrong? (I think it’s about permissions but can’t figure it as I created a single dataset accessible on LAN for root account with 777)

I’m not dealing frequently with FreeNAS but I think the order of operations should be as following:

  • create a new user in Accounts menu (this should correspond to user from the client computer);
  • assign user to a group (either an existing one or create a new group);
  • enable service needed for sharing (NFS/SMB/etc);
  • create data set in Storage->Pools;
  • edit data set permissions for the owner & group (don’t modify for Other) with the user & group defined before to (also set Apply permission recursively);
  • share data set in Sharing menu (NFS/SMB/etc) and input user and group in the advanced mode;
  • mount the data set to the client’s filesystem (Linux/Windows/etc);
  • edit mount points for the jail and add the data set from FreeNAS to jail.

This way, the data set is available to both jail and client computer so antivirus can scan it.

1 Like

Hi,

Could you recommend a not-so-priced server for FreeNAS?

Hi,

Sorry, but no :smile:

I use a regular desktop with Pentium G4400 processor. It doesn’t have a Xeon processor or ECC memory but I managed to add a PCI-E/SATA adapter and PCI-E/Gigabit card so I can use 4 HDDs and link aggregation (although it should be read as load balancing not lagg as the switch doesn’t support it).

For a mere 100 EUR I get stellar performance with redundancy: constant 20-25 MB/s write and 60-70 MB/s read speed wireless (2x2 wireless card through one wall; decreases to about 60% though the second wall; 70-80 MB/s write and 110 MB/s read speed on wire).

For smaller form factor servers I would advice installing FreeNAS on HP Microserver Gen 8 or Gen 10 (Synology devices are definitely the best in class consumer products but in the lower prices region they’re seriously under-powered with ARM processors so you need to pay in excess of 3-4 KEUR for new gear if you need a x86 processor; or go Dark cough-cough (Xpenology) Side; FreeNAS just works on pretty much any x86 processor with official support - off course iXsystems gets free beta testing for TrueNAS, however they do provide a solid freeware product).

For Gen 10 you should follow the instructions here as there are some issues with installation (beside that, I cannot stress enough the importance of using good quality USB sticks for both live and installation drives that would save enough efforts afterwards :wink: )

1 Like

Many thanks

Absolutely Awesome!! thanks a lot! My stepson will hate me :stuck_out_tongue:

I know it’s been a while but i thought i’d share a slight modification that may add some functionality and remove a few steps for some people.

Here’s a modified switch that gets the current status when HA restarts and also doesn’t require putting bash scripts onto the router itself.

Update your key path, router username, router IP and MAC accordingly.

    - platform: command_line
      switches:
        control_internet_host_a:
          command_on: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /config/custom_components/asuswrt_ssh/my.key '[email protected]' iptables -I FORWARD -i br0 -m mac --mac-source 00:00:00:00:00:01 -j DROP"
          command_off: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /config/custom_components/asuswrt_ssh/my.key '[email protected]' iptables -D FORWARD -i br0 -m mac --mac-source 00:00:00:00:00:01 -j DROP" 
          command_state: "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /config/custom_components/asuswrt_ssh/my.key '[email protected]' \"if iptables -L FORWARD -v -n | grep -q '00:00:00:00:00:01' ; then echo 'true'; fi\""
          value_template: '{{ value == "true" }}'
          friendly_name: "Host A Blocked"

Thank you for the original configuration!

2 Likes

Thank you!

There are many ways to skin the cat :slight_smile:

To setup the SSH keys between Hassio and OpenWRT:
(start in Hassio terminal)

cd /root/.ssh
ssh-keygen -t rsa
// Press Enter 3 times
ssh [email protected]
exit
cat /root/.ssh/id_rsa.pub | ssh [email protected] 'cat >> /etc/dropbear/authorized_keys'

My problem, since I’m running OpenWRT, was that the authorized_keys file was located in a different folder in the router.
After doing the above I restarted both HA and OpenWRT and it still works, so for me there is no problem using /root/.ssh in HA to store the files.

EDIT: The above doesn’t work since the user the commands are run as don’t have access to the /root folder.
See more info here.
The main points to get it to work is to put the file in /config/.ssh and then set the correct user on the id_rsa file:

chown hassio:hassio /config/.ssh/id_rsa

Before I did this I could run the commands perfectly from the terminal but the commands failed when using them in an HA Switch.
My switch command ended up like this:

switch:
  - platform: command_line
    switches:
      toggle_lan_devices:
        command_on: /usr/bin/ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/config/.ssh/known_hosts -i /config/.ssh/id_rsa [email protected] iptables -I FORWARD -i br-lan -m mac --mac-source xx:xx:xx:xx:xx:xx -j DROP
        command_off: /usr/bin/ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/config/.ssh/known_hosts -i /config/.ssh/id_rsa [email protected] iptables -D FORWARD -i br-lan -m mac --mac-source xx:xx:xx:xx:xx:xx -j DROP
        command_state: /usr/bin/ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/config/.ssh/known_hosts -i /config/.ssh/id_rsa [email protected] "if iptables -L FORWARD -v -n | grep -q 'xx:xx:xx:xx:xx:xx' ; then echo 'true'; fi"
        value_template: '{{ value == "true" }}'
        friendly_name: "Toggle mac"
1 Like