40

Recently, I have encountered a problem of limiting Internet Access to specific programs. Could anybody recommend a good way of doing that, without using any particular software?

4 Answers 4

53

The solution for me happened to be straight forward.

  1. Create, validate new group; add required users to this group:
    • Create: groupadd no-internet
    • Validate: grep no-internet /etc/group
    • Add user: useradd -g no-internet username

      Note: If you're modifying already existing user you should run: usermod -a -G no-internet userName check with : sudo groups userName

  2. Create a script in your path and make it executable:
  • Create: nano /home/username/.local/bin/no-internet
  • Executable: chmod 755 /home/username/.local/bin/no-internet
  • Content:
#!/bin/bash
sg no-internet "$@"
  1. Add iptables rule for dropping network activity for group no-internet:

    • iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP

      Note: Don't forget to make the changes permanent, so it would be applied automatically after reboot. Doing it, depends on your Linux distribution.
  2. Check it, for example on Firefox by running: no-internet "firefox"

In case you would want to make an exception and allow a program to access local network:

  • iptables -A OUTPUT -m owner --gid-owner no-internet -d 192.168.1.0/24 -j ACCEPT
  • iptables -A OUTPUT -m owner --gid-owner no-internet -d 127.0.0.0/8 -j ACCEPT
  • iptables -A OUTPUT -m owner --gid-owner no-internet -j DROP

NOTE: In case of spawning the rules will be maintained. For example, if you run a program with no-internet rule and that program will open browser window, still the rules will be applied.

12
  • 2
    A few notes Ilia: Ad 1: - to modify existing user: usermod -a -G groupName userName - check with : sudo groups userName Ad 3: - I already have a lot of rules in iptables, The position of the new rule is crucial. should be the first rule in chain OUTPUT. Therefore I use insert : iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP To allow access to LAN: make sure the ACCEPT rules are above the DENY rule. Works like a charm. Use it for example on Wifiguard. Prog checks wlan for unknown devices, but "phones home" on every start.
    – user205602
    Jan 15, 2014 at 14:01
  • The script will only pass the command. If you try launching a programm with parameters, you should use "$@" instead of "$1". For some reason, I had to temporarily store it in a variable for bash to process it correctly: cmd="$@"; sg no-internet "${cmd}"
    – onse
    Oct 20, 2015 at 12:49
  • use "nointernet" instead of "no-internet". For whatever reason Ubuntu 14.04 can't handle the dash when you try to use sg or chgrp (it prompts for a password, then fails).
    – user318195
    Oct 22, 2015 at 20:38
  • 1
    unshare -n YourAppToBlock > use "nointernet" instead of "no-internet". perhaps, 'no\\-internet'?
    – SarK0Y
    Apr 15, 2016 at 22:33
  • I tried it like described but for me, after adding me to "no-internet" and set the ip-tables I cannot connect to the internet anymore (with and without the bash script no-internet).
    – Viatorus
    Jul 26, 2016 at 13:23
23

A more straightforward possibility: use firejail. It runs the application inside sandbox. At the sandbox, you can control the access of the application to any network or folder in your computer.

To execute a certain application without network access do following:

firejail --net=none <application>

In that case, "The sandbox looks like a computer without any network interfaces." (See Network Section in documentation)

For example, firejail --net=none firefox will start firefox without any network connection.

Installation

See the Installation documentation. You should install from the package system in your distribution, or better get the latest version LTS. (For example, this latest LTS version, 9.56.2, works also in Ubuntu 16.04.)

1
  • I am getting following warning message: Warning: an existing sandbox was detected. ping will run without any additional sandboxing features
    – alper
    Jul 2, 2023 at 9:15
11

From answer for How to disable Internet connection for a single process and Block network access of a process

Then, starting a process without network access is as simple as:

unshare -n program ...

This creates an empty network namespace for the process. That is, it is run with no network interfaces, including no loopback. In below example we add -r to run the program only after the current effective user and group IDs have been mapped to the superuser ones (avoid sudo):

unshare -r -n ping google.com

1
  • 1
    I could not run libreoffice6.0 with firejail, but your method worked. :) Mar 5, 2022 at 17:56
1

nftables can set firewall rules based on cgroups (it can be bound to each program), the syntax:

socket cgroupv2 level NUM PATH

PATH:

'PATH' is the one in /sys/fs/cgroup, note that the 'PATH' is relative, so you should exclude /sys/fs/cgroup/ from the absolute path. For example, /sys/fs/cgroup/system.slice/nginx.service is the cgroup for nginx and its 'PATH' should be system.slice/nginx.service.

Most systemd services are confined in cgroups. Use systemd-cgls to view the cgroup tree and use systemd-cgls -u XXX.service to get the cgroup for a specific service. For example, systemd-cgls -u nginx.service returns /system.slice/nginx.service.

Note that you should remove the first / , so the 'PATH' should be system.slice/nginx.service. If your path contains the symbol '@' please use nft --interactive to set up your firewall rules, other wise, the symbol would be misinterpreted.

Although cgroups will be setup for every systemd unit automatically, you can modify or create systemd unit files to fine tune the cgroup settings if you have special needs. Theoretically, you can set up rules for all programs in a systemd enabled operating system. See systemd.unit(5) and systemd.slice(5) for more information.

Even the most basic systemd unit is attached to a cgroup:

[Unit]
Description="My Program"

[Service]
ExecStart="/usr/bin/my_program"

If your do not use systemd, you can also add program to cgroups manually. See cgroups kernel documentation for more info.

NUM:

'NUM' indicates the level of cgroups that will be matched in the firewall rule. In our previous example, socket cgroupv2 level 2 "system.slice/nginx.service" matches exactly the nginx service. While socket cgroupv2 level 1 "system.slice/nginx.service" matches all the cgroups under "system.slice/", thus not only nginx but other programs in that directory will also be matched, such as "snapd.service".

A very basic example:

To prevent nginx from accessing the Internet (assume you already have a inet table named 'filter' and a chain named 'output'):

nft add rule inet filter output socket cgroupv2 level 2 "system.slice/nginx.service" drop
1
  • If you have a systemd service, you can tell systemd itself to run it in an empty network namespace with PrivateNetwork=true; no need for extra tools at that point. Mar 4, 2023 at 21:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .