Est-il possible de bloquer l'accès au réseau (sortant) d'un seul processus?
Avec Linux 2.6.24+ (considéré comme expérimental jusqu'au 2.6.29), vous pouvez utiliser des espaces de noms réseau pour cela. Vous devez activer les "espaces de noms réseau" dans votre noyau (CONFIG_NET_NS=y
) et util-linux avec l'outil unshare
.
Ensuite, démarrer un processus sans accès au réseau est aussi simple que:
unshare -n program ...
Cela crée un espace de noms réseau vide pour le processus. Autrement dit, il est exécuté sans interfaces réseau, y compris sans bouclage . Dans l'exemple ci-dessous, nous ajoutons -r pour exécuter le programme uniquement après que les ID d'utilisateur et de groupe effectifs actuels ont été mappés sur ceux du superutilisateur (évitez Sudo):
$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable
Si votre application a besoin d'une interface réseau, vous pouvez en configurer une nouvelle:
$ unshare -n -- sh -c 'ip link set dev lo up; ping 127.0.0.1'
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=32 time=0.066 ms
Notez que cela créera un nouveau bouclage local . Autrement dit, le processus généré ne pourra pas accéder aux ports ouverts de l'hôte 127.0.0.1
.
Si vous devez accéder à la mise en réseau d'origine à l'intérieur de l'espace de noms, vous pouvez utiliser nsenter
pour entrer dans l'autre espace de noms.
L'exemple suivant exécute ping
avec un espace de noms réseau utilisé par PID 1 (il est spécifié via -t 1
):
$ nsenter -n -t 1 -- ping -c4 example.com
PING example.com (93.184.216.119) 56(84) bytes of data.
64 bytes from 93.184.216.119: icmp_seq=1 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=2 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=3 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=4 ttl=50 time=139 ms
--- example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 134.621/136.028/139.848/2.252 ms
Linux a une fonctionnalité appelée espaces de noms résea qui vous permet d'avoir essentiellement plusieurs piles réseau sur la même machine et d'en affecter une à un programme lors de son exécution. Il s'agit d'une fonctionnalité généralement utilisée pour les conteneurs, mais vous pouvez également l'utiliser pour accomplir ce que vous voulez.
Le ip netns
les sous-commandes le gèrent. La création d'un nouvel espace de noms réseau sans accès à quoi que ce soit est facile, c'est l'état par défaut d'un nouvel espace de noms:
root@Host:~# ip netns add jail
Maintenant, si vous basculez vers cet espace de noms, vous pouvez le configurer assez facilement. Vous voudrez probablement en parler, et c'est tout:
root@Host:~# ip netns exec jail /bin/bash
root@Host:~# ip addr add 127.0.0.1/8 dev lo
root@Host:~# ip link set dev lo up
root@Host:~# exit
Maintenant, lorsque vous souhaitez exécuter votre commande sans réseau, vous l'exécutez simplement dans cette prison:
root@Host:~# ip netns exec jail su user -c 'ping 8.8.8.8'
connect: Network is unreachable
Le réseau est, comme souhaité, inaccessible. (Vous pouvez faire toutes sortes de choses intéressantes car une pile réseau distincte inclut des règles iptables
, etc.)
Vous pouvez utiliser iptables et déplacer ce processus dans un groupe de contrôle:
mkdir /sys/fs/cgroup/net_cls/block
echo 42 > /sys/fs/cgroup/net_cls/block/net_cls.classid
iptables -A OUTPUT -m cgroup --cgroup 42 -j DROP
echo [pid] > /sys/fs/cgroup/net_cls/block/tasks
Oui, avec un profil d'apparmeur personnalisé, c'est-à-dire
/usr/bin/curl {
...
# block ipv4 acces
deny network inet,
# ipv6
deny network inet6,
# raw socket
deny network raw,
}
Mais de cette façon, vous devrez également générer une liste de fichiers autorisés à accéder, toute la procédure peut être un peu compliquée. Et voir le document d'aide ici
Vous pouvez utiliser sandbox firejail (devrait fonctionner sur les noyaux avec la fonction seccomp).
Pour l'utiliser, il suffit de faire
firejail --noprofile --net=none <path to executable>
--noprofile
désactive le sandbox par défaut --net=none
désactive la mise en réseau
Je crois que la plupart des distributions fournissent déjà un paquet, mais même si elles ne font pas firejail, elles n'ont pratiquement aucune dépendance autre que la chaîne d'outils de construction et le noyau activé namespace/seccomp.
Il existe d'autres fonctionnalités intéressantes de Firejail qui peuvent être affichées avec firejail --help
en ce qui concerne la mise en réseau (comme fournir uniquement une interface de bouclage ou bloquer ip/dns, etc.) mais cela devrait faire l'affaire. En outre, il doesn't require root
.
Vous ne pouvez pas le faire avec iptables seul. Cette fonctionnalité existait brièvement , mais ne pouvait pas fonctionner de manière fiable et a été abandonnée.
Si vous pouvez exécuter le processus en tant qu'ID utilisateur dédié, iptables peut le faire avec le module owner
:
iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP
Voir les exemples dans Iptables: faire correspondre le trafic sortant avec conntrack et le propriétaire. Fonctionne avec des gouttes étranges , règle iptables/pf pour autoriser uniquement l'application/utilisateur XY?
Si vous pouvez exécuter le processus dans son propre conteneur, vous pouvez pare-feu ce conteneur indépendamment (même le rendre complètement déconnecté du réseau).
Un module de sécurité peut filtrer l'accès d'un processus aux fonctionnalités de mise en réseau. réponse de warl0ck donne un exemple avec AppArmor.
Solution 1: Pare-feu:
Nous pourrions utiliser des pare-feu comme Douane ou Opensnitch MAIS ces applications ne sont pas efficaces à 100% ou à un stade précoce de développement (ont beaucoup de bogues, etc. à partir de 2019)
Solution 2: MAC du noyau:
Les MAC du noyau peuvent être utilisés comme pare-feu les plus connus sont Tomoyo , Selinux et Apparmor Cette solution est la meilleure en termes de stabilité et d'efficacité (solution de pare-feu) mais la plupart du temps, la configuration est en quelque sorte compliquée.
Solution 3: Firejail:
Firejail peut être utilisé pour bloquer l'accès au réseau pour une application cela ne nécessite pas de root, tout utilisateur peut en bénéficier
firejail --noprofile --net=none command-application
Solution 4: Annuler le partage
L'annulation du partage peut démarrer une application sur une autre appellation sans réseau, mais cela nécessite la solution root de firejail fait presque exactement la même chose mais ne nécessite pas root
unshare -r -n application-comand
Solution 5: Proxify:
Une solution consiste à proclamer l'application à un proxy null/faux . Nous pouvons utiliser tsocks ou proxybound . Voici quelques détails sur la configuration
Solution 6: Iptables:
Une autre solution simple est iptables, elle pourrait être configurée pour bloquer une application
groupadd no-internet
grep no-internet /etc/group
useradd -g no-internet username
usermod -a -G no-internet userName
vérifier avec : Sudo groups userName
nano /home/username/.local/bin/no-internet
chmod 755 /home/username/.local/bin/no-internet
#!/bin/bash
sg no-internet "$@"
iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP
4. Vérifiez-le, par exemple sur Firefox en exécutant:
no-internet "firefox"
5. Au cas où vous voudriez faire une exception et autoriser un programme à accéder à réseau local:
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
6. Rendez-le permanent
Une façon d'appliquer la règle iptables au démarrage consiste à ajouter la règle en tant que service avec systemd
cat /usr/lib/systemd/system/nonet.service
[Unit]
Description=Nonet group iptable update
After=network.target
After=xsession.target
After=iptables.service
After=shorewall.service
[Service]
Type=oneshot
RemainAfterExit=true
StandardOutput=journal
ExecStart=/bin/bash /home/user/Scripts/Nonet.iptables.sh
Cela dépend de la distribution que vous utilisez, mais c'est une fonctionnalité généralement incluse dans le système MAC du système d'exploitation. Comme indiqué précédemment, Ubuntu ou AppArmor de SuSE peuvent le faire. Si vous utilisez RHEL, vous pouvez configurer SELinux pour autoriser ou refuser l'accès à un numéro de port particulier en fonction de l'étiquette du processus d'exécution. This est tout ce que j'ai pu trouver après quelques recherches rapides sur Google, mais il y a probablement des ressources plus détaillées en ligne si vous regardez plus attentivement et cela vous donne une idée générale.
Vous pouvez utiliser seccomp-bpf pour bloquer certains appels système. Par exemple, vous voudrez peut-être bloquer l'appel système socket
afin d'empêcher le processus de créer des sockets FD.
J'ai écrit un exemple de cette approbation qui empêche l'appel système socket
de travailler avec libseccomp. Le résumé est (sans vérification d'erreur):
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_Arch_add(ctx, SCMP_Arch_NATIVE);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, pf));
seccomp_load(ctx);
execvp(argv[1], argv+1);
Cela n'a pas besoin de privilèges root.
Un sandbox complet est cependant beaucoup plus complexe, vous ne devez donc pas utiliser cette commande pour bloquer les programmes non coopératifs/malveillants.
Depuis Systemd v235, il existe également une autre option très simple:
comptabilité IP et listes d'accès avec systemd
TL; DR: systemd peut désormais effectuer la comptabilité du trafic IP par service, ainsi que le contrôle d'accès pour les plages d'adresses IP.