Bloquer l'accès réseau d'un processus?

74

Est-il possible de bloquer l'accès réseau (sortant) d'un processus unique?

larkee
la source
6
Comment comptez-vous identifier le processus? PID, nom, chemin d'accès?
Marco
1
Quel accès voulez-vous bloquer? Certains programmes utilisent un accès réseau via localhost(au même ordinateur) pour effectuer leur travail.
vonbrand
Voir aussi LD_PRELOAD ou similaire pour empêcher l'accès au réseau , si le processus coopère.
Gilles 'SO- arrête d'être méchant'

Réponses:

78

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. Les 'espaces de noms réseau' doivent être activés dans votre noyau ( CONFIG_NET_NS=y) et util-linux avec l' unshareoutil.

Ensuite, démarrer un processus sans accès réseau est aussi simple que:

unshare -n program ...

Cela crée un espace de nom de réseau vide pour le processus. C'est-à-dire qu'il est exécuté sans aucune interface réseau, y compris aucune boucle de rappel . Dans l'exemple ci-dessous, nous ajoutons -r pour exécuter le programme uniquement après que les ID utilisateur et groupe actuels ont été mappés sur ceux du super-utilisateur (éviter sudo):

$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable

Si votre application nécessite une interface réseau, vous pouvez en créer 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 créé ne pourra pas accéder aux ports ouverts de l'hôte 127.0.0.1.


Si vous avez besoin d'accéder au réseau d'origine à l'intérieur de l'espace de noms, vous pouvez utiliser nsenterpour entrer l'autre espace de noms.

L'exemple suivant s'exécute pingavec un espace de noms réseau utilisé par le PID 1 (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
Michał Górny
la source
4
unshare -nsemble jeter "Opération non autorisée" sans rootprivilèges, tout ce qui me manque à ce sujet?
baldrs
1
Peut-être une question stupide ... Cet espace de noms s'applique-t-il également aux processus enfants / appelés processus de l'application non partagée?
bonanza
3
Oui. Il est hérité par tous les enfants engendrés après le basculement de l'espace de noms.
Michał Górny le
2
Je ressemble à tous les programmes que je voudrais ne pas partager, par exemple, avec sudo unshare -nle droit racine. Comme j'ai besoin que le sudo appelle unshare, je me demande comment je peux m'assurer que le programme appelé n'a pas les droits root.
bonanza
3
Une ligne pour limiter le processus à un utilisateur. Deux fois plus de sudo: sudo unshare -n sudo -u dude bash -c 'echo Hello, my name is $USER'@ThorSummoner bbs.archlinux.org/viewtopic.php?id=205240
Jakub Bochenski
21

Linux possède une fonctionnalité appelée espaces de noms réseau qui vous permet d’avoir essentiellement plusieurs piles réseau sur le même ordinateur et d’en assigner une à un programme lors de son exécution. C'est une fonctionnalité généralement utilisée pour les conteneurs, mais vous pouvez également l'utiliser pour accomplir ce que vous voulez.

Les ip netnssous-commandes le gèrent. Créer un nouvel espace de noms réseau sans accès à rien 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 voulez exécuter votre commande sans réseau, vous devez simplement l'exécuter 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 vous le souhaitez, inaccessible. (Vous pouvez faire toutes sortes de choses intéressantes en tant que pile réseau séparée comprenant des iptablesrègles, etc.)

derobert
la source
Bien que j'avais besoin sudo ipd'exécuter les commandes ip, une fois que j'étais dans bash, je viens de l'exécuter su someuserpour obtenir un shell non privilégié pour l'utilisateur 'someuser'.
Sage
11

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
Jan Mueller
la source
1
comment enlever le pid de ce fichier de tâches son donner erreur quand im essayant de supprimer ou de supprimer des données de ce fichier si im avec l'utilisateur root
pkm
@pkm pour permettre la mise en réseau, il vous suffit de faire écho à [pid] pour /sys/fs/cgroup/net_cls/tasks(pas de 'blocage' dans le chemin)
chagrin
10

Oui, avec profil Apparmor personnalisé, c.-à-d.

/usr/bin/curl {
    ...

    # block ipv4 acces
    deny network inet,
    # ipv6 
    deny network inet6,
    # raw socket
    deny network raw,

}

Mais de cette façon, vous aurez besoin de générer une liste de fichiers autorisés à accéder également. Toute la procédure peut être un peu compliquée. Et voir le document d'aide ici

Marguerite
la source
7

Vous pouvez utiliser le bac à sable firejail (devrait fonctionner sur les noyaux avec la fonction seccomp).

Pour l'utiliser, il suffit de

firejail --noprofile --net=none <path to executable>

--noprofiledésactive le sandbox par défaut --net=nonedésactive la mise en réseau

Je pense que la plupart des distributions fournissent déjà un paquet, mais même si elles ne tirent pas dessus, il n’existe pratiquement pas de dépendances autres que build toolchain et namespace / seccomp.

Firejail offre d’autres fonctionnalités intéressantes firejail --help, comme le fait de ne fournir que l’interface de bouclage ou de bloquer les adresses IP / DNS, etc.), mais cela devrait suffire. Aussi, ça doesn't require root.

pruzinat
la source
5

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 ownermodule:

iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP

Voir des exemples dans Iptables: correspondance du trafic sortant avec conntrack et propriétaire. Fonctionne avec des gouttes étranges , la règle iptables / pf ne permettant que les applications / utilisateurs XY?

Si vous pouvez exécuter le processus dans son propre conteneur, vous pouvez pare-feu de manière indépendante sur ce conteneur (même s'il est complètement déconnecté du réseau).

Un module de sécurité peut filtrer l'accès d'un processus aux fonctionnalités réseau. La réponse de warl0ck donne un exemple avec AppArmor.

Gilles, arrête de faire le mal
la source
3

Solution 1: Pare-feu:

Nous pourrions utiliser des pare-feu comme Douane ou Opensnitch MAIS ces applications ne sont pas efficaces à 100% ou sont à un stade précoce de développement (ont beaucoup de bugs, etc. à partir de 2019)

Solution 2: MAC du noyau:

Les MAC du noyau peuvent être utilisés comme pare-feu. Les solutions les plus connues 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, il est assez compliqué de la définir.

Solution 3: Firejail:

Firejail peut être utilisé pour bloquer l’accès au réseau d’une application qui ne nécessite pas d’utilisateur root, aucun utilisateur ne pouvant en bénéficier.

firejail --noprofile --net=none command-application

Solution 4: annuler le partage

Unshare peut démarrer une application sur une adresse de nom différente sans réseau, mais cela nécessite la solution de root firejail qui fait presque exactement la même chose mais ne nécessite pas de root.

unshare -r -n application-comand

Solution 5: Proxify:

Une solution consiste à proxy l’application sur un proxy null / faux . Nous pouvons utiliser tsocks ou proxybound . Voici quelques détails sur la configuration

Solution 6: Iptables:

Une autre solution facile est iptables, il pourrait être configuré pour bloquer une application

  1. Créer, valider un nouveau groupe ; ajouter les utilisateurs requis à ce groupe:
    • Créer: groupadd no-internet
    • Valider: grep no-internet /etc/group
    • Ajouter un utilisateur: useradd -g no-internet username

      Remarque: Si vous modifiez un utilisateur déjà existant, vous devez exécuter: usermod -a -G no-internet userName vérifier avec:sudo groups userName

  2. Créez un script dans votre chemin et rendez-le exécutable:
    • Créer: nano /home/username/.local/bin/no-internet
    • Exécutable: chmod 755 /home/username/.local/bin/no-internet
    • Contenu: #!/bin/bash
                    sg no-internet "$@"

  3. Ajouter une règle iptables pour la suppression d'activité réseau pour le groupe no-internet :


   4. Vérifiez-le, par exemple sur Firefox en exécutant:

  • no-internet "firefox"

   5. Si vous souhaitez créer une exception et autoriser un programme à accéder au 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. le rendre permanent

   Une façon d’appliquer la règle iptables au démarrage est d’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
intika
la source
1
Ceci est un excellent guide. Je vous remercie. Bien que, pour moi, ma commande no-internet ne semble jamais passer le paramètre, alors je l'utilise sg no-internetpour le moment.
Zach Bloomquist le
@Zach, j'ai mis à jour ma réponse, vous pouvez être intéressé par firejail;)
intika
2

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 en cours d'exécution. C’est tout ce que je pouvais trouver après une recherche rapide sur Google, mais il existe probablement des ressources plus détaillées en ligne si vous cherchez plus et vous donne l’idée générale.

Bratchley
la source
2

Vous pouvez utiliser seccomp-bpf pour bloquer certains appels système. Par exemple, vous pouvez vouloir bloquer l'socket appel système afin d'empêcher le processus de créer des FD de sockets.

J'ai écrit un exemple de cet approcah qui empêche l' socketappel système 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 beaucoup plus complexe, vous ne devez donc pas utiliser cet ordre pour bloquer les programmes non coopératifs / malveillants.

ysdx
la source
Pouvez-vous donner un exemple d'utilisation? Est-ce que cela nécessite des privilèges root pour fonctionner?
bonanza
-4

Vous pouvez utiliser un programme en ligne de commande appelé "proxychains" et essayer l’une des possibilités suivantes:

Configurez-le qu'il utilise ...

  • ... un proxy qui n'existe pas? (Je ne sais pas s'il l'exécutera avec un proxy "invalide")
  • ... un proxy local (comme "tinyproxy", "squid", "privoxy", ...) qui limite l'accès à Internet? (Utilisez simplement des ACL)

Je ne l'ai pas testé moi-même, donc je ne sais pas si cela fonctionne ...

drkhsh
la source
Publier des solutions non testées n'est généralement pas une bonne idée.
Twirrim
Les chaînes de substitution avec un proxy non existant (comme localhost: 1234 ou similaire) pourraient en réalité constituer une approche solide, cependant
phil294