Les processus non root peuvent-ils se lier à & # 8220; privilégié & # 8221; des ports sur Linux?

StackOverflow https://stackoverflow.com/questions/413807

Question

Il est très agaçant d’avoir cette limitation dans ma boîte de développement, alors qu’il n’y aura jamais d’utilisateurs autres que moi.

Je connais les solutions palliatives standard , mais aucune d'entre elles ne fait exactement ce que Je veux:

  1. authbind (version dans Debian testing, 1.0, ne supportant que IPv4)
  2. utiliser la cible iptables REDIRECT pour rediriger un port bas vers un port élevé (la table "nat" n'est pas encore implémentée pour ip6tables, la version IPv6 de iptables)
  3. sudo (j'essaie d'éviter de fonctionner en tant que root)
  4. SELinux (ou similaire). (Ceci est juste ma boîte de dev, je ne veux pas introduire beaucoup de complexité supplémentaire.)

Existe-t-il une simple variable sysctl permettant aux processus non root de se lier à " privilégié " ports (ports inférieurs à 1024) sur Linux, ou est-ce que je viens de manquer de chance?

EDIT: Dans certains cas, vous pouvez utilisez les fonctionnalités pour ce faire.

Était-ce utile?

La solution

D'accord, merci aux personnes qui ont signalé le système de fonctionnalités et la fonctionnalité CAP_NET_BIND_SERVICE . Si vous avez un noyau récent, il est en effet possible de l'utiliser pour démarrer un service en tant que lecteur non root mais lier des ports faibles. La réponse courte est que vous faites:

setcap 'cap_net_bind_service=+ep' /path/to/program

Ensuite, chaque fois que le programme est exécuté, il aura la capacité CAP_NET_BIND_SERVICE . setcap est dans le paquet Debian libcap2-bin .

Maintenant pour les mises en garde:

  1. Vous aurez besoin d'au moins un noyau 2.6.24
  2. Cela ne fonctionnera pas si votre fichier est un script. (c’est-à-dire qu’il utilise une ligne #! pour lancer un interprète). Dans ce cas, autant que je sache, vous devez appliquer la capacité à l'exécutable de l'interprète lui-même, ce qui est bien sûr un cauchemar pour la sécurité, car tout programme utilisant cet interprète en aura la capacité. Je n'ai pas réussi à trouver un moyen simple et clair de contourner ce problème.
  3. Linux désactivera LD_LIBRARY_PATH sur tout programme disposant de privilèges élevés, comme setcap ou suid . Donc, si votre programme utilise son propre ... / lib / , vous devrez peut-être envisager une autre option, telle que la redirection de port.

Ressources:

Remarque: RHEL a d'abord ajouté cela dans la v6 .

Autres conseils

La méthode standard consiste à les rendre "setuid". afin qu’ils démarrent en tant que root, puis jettent ce privilège root dès qu’ils sont liés au port, mais avant qu’ils ne commencent à accepter les connexions. Vous pouvez en voir de bons exemples dans le code source d’Apache et de INN. On me dit que Lighttpd est un autre bon exemple.

Un autre exemple est Postfix, qui utilise plusieurs démons qui communiquent via des canaux. Seuls un ou deux d’entre eux (qui ne font que très peu sauf accepter ou émettre des octets) s’exécutent en tant que root et le reste fonctionne avec un privilège inférieur.

Vous pouvez faire une redirection de port. C’est ce que je fais pour un serveur de règles Silverlight fonctionnant sur une machine Linux

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 943 -j REDIRECT --to-port 1300

Vous pouvez configurer un tunnel SSH local, par exemple si vous souhaitez que le port 80 frappe votre application liée à 3000:

sudo ssh $USERNAME@localhost -L 80:localhost:3000 -N

Cela présente l'avantage de travailler avec des serveurs de script et d'être très simple.

Ou corrigez votre noyau et supprimez la vérification.

(Option de dernier recours, non recommandé).

Dans net / ipv4 / af_inet.c , supprimez les deux lignes indiquant

      if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
              goto out;

et le noyau ne vérifiera plus les ports privilégiés.

Les fonctionnalités de fichier ne sont pas idéales, car elles peuvent se rompre après la mise à jour d'un package.

La solution idéale, à mon humble avis, devrait être la possibilité de créer un shell avec CAP_NET_SERVICE définissable.

.

Voici une façon un peu compliquée de faire cela:

sg $DAEMONUSER "capsh --keep=1 --uid=`id -u $DAEMONUSER` \
     --caps='cap_net_bind_service+pei' -- \
     YOUR_COMMAND_GOES_HERE"
L'utilitaire

capsh est disponible dans le paquet libcap2-bin des distributions Debian / Ubuntu. Voici ce qui se passe:

  • sg remplace l'identifiant de groupe effectif par celui de l'utilisateur démon. Cela est nécessaire car capsh ne modifie pas l'identifiant GID et nous ne le souhaitons absolument pas.
  • Définit le bit 'conserver les capacités lors de la modification de l'UID'.
  • Remplace l'UID par $ DAEMONUSER
  • Supprime toutes les majuscules (à ce moment, toutes les majuscules sont toujours présentes à cause de - keep = 1 ), à l'exception du héritable cap_net_bind_service
  • Exécute votre commande ('-' est un séparateur)

Le résultat est un processus avec l'utilisateur et le groupe spécifiés, ainsi que les privilèges cap_net_bind_service .

Par exemple, une ligne du script de démarrage ejabberd :

sg $EJABBERDUSER "capsh --keep=1 --uid=`id -u $EJABBERDUSER` --caps='cap_net_bind_service+pei' -- $EJABBERD --noshell -detached"

Deux autres possibilités simples:

Il existe une ancienne solution (non à la mode) au "démon qui se lie sur un port faible et au contrôle de votre démon". Cela s'appelle inetd (ou xinetd). Les inconvénients sont:

  • votre démon doit parler sur stdin / stdout (si vous ne contrôlez pas le démon - si vous n'avez pas la source - alors c'est peut-être un spectacle, bien que certains services puissent avoir un indicateur de compatibilité inetd )
  • un nouveau processus démon est créé pour chaque connexion
  • c'est un maillon supplémentaire de la chaîne

Avantages:

  • disponible sur tout ancien UNIX
  • une fois que votre administrateur système a configuré la configuration, vous pouvez poursuivre votre développement (lorsque vous reconstruisez votre démon, risque-t-il de perdre des capacités setcap? Ensuite, vous devrez revenir à votre administrateur " s'il vous plaît monsieur ... ")
  • le démon n'a pas à s'inquiéter de ce genre de réseau, il suffit de parler sur stdin / stdout
  • peut configurer l'exécution de votre démon en tant qu'utilisateur non root, comme demandé

Une autre alternative: un proxy piraté (netcat ou même quelque chose plus robuste ) du port privilégié à un port arbitraire portant un numéro élevé où vous pouvez exécuter votre démon cible. (Netcat n'est évidemment pas une solution de production, mais "juste ma boîte de développement", n'est-ce pas?). De cette façon, vous pouvez continuer à utiliser une version de votre serveur compatible réseau, vous n’auriez besoin que de root / sudo pour démarrer le proxy (au démarrage), sans compter sur des capacités complexes / potentiellement fragiles.

Mon "Contournement standard" " utilise socat comme redirecteur d'espace utilisateur:

socat tcp6-listen:80,fork tcp6:8080

Méfiez-vous que cela ne sera pas à l’échelle, le bricolage coûte cher, mais c’est ainsi que fonctionne le socat.

Mise à jour 2017:

Utilisez authbind


Beaucoup mieux que CAP_NET_BIND_SERVICE ou un noyau personnalisé.

  • CAP_NET_BIND_SERVICE accorde la confiance au binaire mais ne fournit pas contrôle sur l'accès par port.
  • Authbind accorde la confiance au utilisateur / groupe et permet de contrôler l'accès par port, et prend en charge IPv4 et IPv6 (la prise en charge IPv6 a été ajoutée récemment).

    1. Installer: apt-get install authbind

    2. Configurez l'accès aux ports appropriés, par exemple. 80 et 443 pour tous les utilisateurs et groupes:

        

      sudo touch / etc / authbind / byport / 80
        sudo touch / etc / authbind / byport / 443
        sudo chmod 777 / etc / authbind / byport / 80
        sudo chmod 777 / etc / authbind / byport / 443

    3. Exécutez votre commande via authbind
      (spécifiant éventuellement - deep ou d'autres arguments, voir la page de manuel):

      authbind --deep /path/to/binary command line args
      

      par exemple.

      authbind --deep java -jar SomeServer.jar
      

Pour faire suite à la recommandation fabuleuse (= déconseillée si vous ne savez pas ce que vous faites) de Joshua: pirater le noyau:

Je l'ai d'abord posté ici .

Simple. Avec un noyau normal ou ancien, ce n'est pas le cas.
Comme l'ont souligné d'autres personnes, iptables peut transférer un port.
Comme d'autres l'ont également souligné, CAP_NET_BIND_SERVICE peut également faire le travail.
Bien sûr, CAP_NET_BIND_SERVICE échouera si vous lancez votre programme à partir d'un script, à moins que vous ne fixiez la limite à l'interpréteur de shell, ce qui est inutile, vous pourriez tout aussi bien exécuter votre service en tant que root ...
par exemple. pour Java, vous devez l’appliquer à la JVM JAVA

sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-8-openjdk/jre/bin/java

Évidemment, cela signifie donc que tout programme Java peut lier des ports système.
Dito pour mono / .NET.

Je suis également convaincu que xinetd n'est pas la meilleure des idées.
Mais puisque les deux méthodes sont des bidouilles, pourquoi ne pas simplement lever la limite en levant la restriction?
Personne n'a dit que vous devez exécuter un noyau normal, vous pouvez donc utiliser le vôtre.

Vous venez de télécharger le code source du dernier noyau (ou du même logiciel que vous avez actuellement). Ensuite, vous allez à:

/usr/src/linux-<version_number>/include/net/sock.h:

Là vous cherchez cette ligne

/* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK       1024

et remplacez-le par

#define PROT_SOCK 0

si vous ne voulez pas avoir une situation ssh peu sûre, vous la changez comme suit:     #define PROT_SOCK 24

En règle générale, j'utiliserais le paramètre le plus bas dont vous avez besoin, par exemple 79 pour http ou 24 lorsque vous utilisez SMTP sur le port 25.

C'est déjà tout.
Compilez le noyau et installez-le.
Redémarrer.
Terminé - cette limite stupide est GONE, et cela fonctionne également pour les scripts.

Voici comment vous compilez un noyau:

https://help.ubuntu.com/community/Kernel/Compile

# You can get the kernel-source via package linux-source, no manual download required
apt-get install linux-source fakeroot

mkdir ~/src
cd ~/src
tar xjvf /usr/src/linux-source-<version>.tar.bz2
cd linux-source-<version>

# Apply the changes to PROT_SOCK define in /include/net/sock.h

# Copy the kernel config file you are currently using
cp -vi /boot/config-`uname -r` .config

# Install ncurses libary, if you want to run menuconfig
apt-get install libncurses5 libncurses5-dev

# Run menuconfig (optional)
make menuconfig

# Define the number of threads you wanna use when compiling (should be <number CPU cores> - 1), e.g. for quad-core
export CONCURRENCY_LEVEL=3
# Now compile the custom kernel
fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers

# And wait a long long time

cd ..

En résumé, utilisez iptables si vous voulez rester en sécurité, compilez le noyau si vous voulez être sûr que cette restriction ne vous dérange plus.

Linux prend en charge les fonctionnalités pour prendre en charge des autorisations plus détaillées que celle-ci: exécuter en tant que root " ;. Une de ces fonctionnalités est CAP_NET_BIND_SERVICE , qui concerne la liaison à un port privilégié (< 1024).

Malheureusement, je ne sais pas comment exploiter cela pour exécuter une application en tant que non-root tout en lui donnant CAP_NET_BIND_SERVICE (probablement en utilisant setcap , mais il doit exister une solution existante).

Je sais que c'est une vieille question, mais maintenant, avec les noyaux récents (> = 4.3), il existe enfin une bonne réponse à cette question: les capacités ambiantes.

La réponse rapide est de récupérer une copie de la dernière version (non encore publiée) de libcap à partir de git et compilez-le. Copiez le binaire progs / capsh résultant quelque part ( / usr / local / bin est un bon choix). Ensuite, en tant que root, démarrez votre programme avec

/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
    --inh='cap_net_bind_service' --addamb='cap_net_bind_service' \ 
    -- -c 'your-program'

Dans l'ordre, nous sommes

  • En déclarant que lorsque nous changeons d'utilisateur, nous voulons conserver nos ensembles de capacités actuels
  • Changement d'utilisateur & amp; groupe à 'votre-nom-service-service'
  • Ajout de la fonctionnalité cap_net_bind_service au fichier hérité & amp; ensembles ambiants
  • Forking bash -c 'votre-commande' (puisque capsh démarre automatiquement bash avec les arguments après - )

Il se passe beaucoup de choses sous le capot ici.

Tout d’abord, nous fonctionnons en tant que root. Par conséquent, nous disposons par défaut d’un ensemble complet de fonctionnalités. Inclus dans ceci est la possibilité de changer uid & amp; gid avec les appels système setuid et setgid . Cependant, normalement, lorsqu'un programme fait cela, il perd son ensemble de capacités - c'est pour que l'ancienne méthode de suppression de racine avec setuid fonctionne toujours. L’indicateur - keep = 1 indique à capsh d’émettre le prctl (PR_SET_KEEPCAPS) syscall, qui désactive la suppression de fonctionnalités lors du changement d’utilisateur. Le changement effectif d'utilisateurs par capsh a lieu avec l'indicateur - user , qui exécute setuid et setgid .

Le problème suivant que nous devons résoudre est la façon de définir les capacités de manière à ce que nous exécutions nos enfants. Le système de capacités a toujours eu un ensemble de capacités "héritées", à savoir "" un ensemble de capacités préservées sur un execve (2) " [ fonctionnalités (7) ]. Bien que cela semble résoudre notre problème (définissez simplement la capacité cap_net_bind_service sur héritée, n'est-ce pas?), Cela ne s'applique en fait qu'aux processus privilégiés - et notre processus n'est plus privilégié, car nous avons déjà changé d'utilisateur ( avec le drapeau - utilisateur ).

Le nouvel ensemble de capacités ambiantes résout ce problème: il s'agit d'un "ensemble de fonctionnalités qui sont préservées sur un execve (2) d'un programme non privilégié." En plaçant cap_net_bind_service dans le jeu d'ambiances, lorsque capsh exécute notre programme serveur, notre programme héritera de cette fonctionnalité et pourra lier les écouteurs à des ports bas.

Si vous souhaitez en savoir plus, consultez les page de manuel explique cela en détail. Exécuter capsh via strace est également très instructif!

TLDR: pour "la réponse" (à mon avis), sautez vers le > > TLDR < < participer à cette réponse.

OK, je l’ai compris (pour de vrai cette fois), la réponse à cette question, et ma réponse est aussi un moyen de s’excuser pour avoir promu autre réponse (ici et sur Twitter) que je pensais être" la meilleure ", mais après l'avoir essayée, j'ai découvert que je m'étais trompé à ce sujet. Apprenez de mon erreur, les enfants: ne faites pas la promotion de quelque chose avant de l'avoir essayé vous-même!

Encore une fois, j’ai passé en revue toutes les réponses ici. J'ai essayé certains d'entre eux (et j'ai choisi de ne pas en essayer d'autres parce que je n'aimais tout simplement pas les solutions). Je pensais que la solution consistait à utiliser systemd avec ses paramètres Capabilities = et CapabilitiesBindingSet = . Après avoir lutté avec cela pendant un certain temps, j'ai découvert que ce n'était pas la solution car:

Les fonctionnalités visent à limiter les processus racine!

Comme l'OP l'a sagement indiqué, il est toujours préférable d'éviter cela (pour tous vos démons si possible!).

Vous ne pouvez pas utiliser les options liées à Capabilities avec Utilisateur = et Groupe = dans les fichiers d'unité systemd , car les fonctionnalités disponibles sont ALWAYS est réinitialisé lorsque execev (ou quelle que soit la fonction) est appelé. En d'autres termes, lorsque systemd divise ses licences en permutant, les fonctionnalités sont réinitialisées. Il n'y a pas moyen de contourner cela, et toute cette logique de liaison dans le noyau est basique autour de uid = 0, pas de capacités. Cela signifie qu'il est peu probable que Capabilities fournira jamais la bonne réponse à cette question (du moins dans un avenir rapproché). Incidemment, setcap , comme d'autres l'ont mentionné, n'est pas une solution. Cela n'a pas fonctionné pour moi, cela ne fonctionne pas très bien avec les scripts et ceux-ci sont réinitialisés de toute façon à chaque modification du fichier.

Dans ma maigre défense, j’ai indiqué (dans le commentaire que j’ai maintenant supprimé) que cette iptables de James suggestion (que le PO mentionne également), était la "2e meilleure solution". :-P

> > TLDR < <

La solution consiste à combiner systemd avec des commandes iptables à la volée, comme ceci ( extrait de DNSChain ):

[Unit]
Description=dnschain
After=network.target
Wants=namecoin.service

[Service]
ExecStart=/usr/local/bin/dnschain
Environment=DNSCHAIN_SYSD_VER=0.0.1
PermissionsStartOnly=true
ExecStartPre=/sbin/sysctl -w net.ipv4.ip_forward=1
ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
User=dns
Group=dns
Restart=always
RestartSec=5
WorkingDirectory=/home/dns
PrivateTmp=true
NoNewPrivileges=true
ReadOnlyDirectories=/etc

# Unfortunately, capabilities are basically worthless because they're designed to restrict root daemons. Instead, we use iptables to listen on privileged ports.
# Capabilities=cap_net_bind_service+pei
# SecureBits=keep-caps

[Install]
WantedBy=multi-user.target

Nous accomplissons les tâches suivantes:

  • Le démon écoute 5333, mais les connexions sont acceptées avec succès grâce à iptables
  • Nous pouvons inclure les commandes dans le fichier d'unité, ce qui évite les maux de tête aux gens. systemd nettoie pour nous les règles de pare-feu, en veillant à les supprimer lorsque le démon n'est pas en cours d'exécution.
  • Nous ne courons jamais en tant qu'utilisateur root et nous rendons impossible l'élévation des privilèges (au moins à à ), même si le démon est compromis et définit uid = 0 .

iptables est malheureusement toujours un utilitaire assez laid et difficile à utiliser. Si le démon écoute eth0: 0 au lieu de eth0 , par exemple, les commandes sont légèrement différent .

systemd est un remplacement sysvinit doté d'une option permettant de lancer un démon doté de fonctionnalités spécifiques. . Options Capabilities =, CapabilityBoundingSet = in systemd.exec (5) .

La redirection de port nous paraissait la plus logique, mais nous avons rencontré un problème où notre application résolvait localement une URL qui devait également être redirigée. (Cela signifie que vous shindig ).

Cela vous permettra également d'être redirigé lorsque vous accédez à l'URL sur la machine locale.

iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A OUTPUT -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080

Pour une raison quelconque, personne ne mentionne la possibilité d'abaisser sysctl net.ipv4.ip_unprivileged_port_start à la valeur dont vous avez besoin. Exemple: nous devons lier notre application au port 443.

sysctl net.ipv4.ip_unprivileged_port_start=443

Certains pourraient dire qu’il existe un problème de sécurité potentiel: les utilisateurs non privilégiés peuvent désormais se connecter aux autres ports privilégiés (444-1024). Mais vous pouvez résoudre ce problème facilement avec iptables, en bloquant d’autres ports:

iptables -I INPUT -p tcp --dport 444:1024 -j DROP
iptables -I INPUT -p udp --dport 444:1024 -j DROP

Comparaison avec d’autres méthodes. Cette méthode:

  • à un moment donné (IMO) est encore plus sûr que de définir CAP_NET_BIND_SERVICE / setuid, puisqu’une application n’a pas du tout setuid, même partiellement (les capacités le sont réellement). Par exemple, pour intercepter une application remplissant des fonctionnalités, vous devez modifier sysctl fs.suid_dumpable (ce qui entraîne d'autres problèmes de sécurité potentiels). En outre, lorsque CAP / suid est défini, le répertoire / proc / PID appartient à root. Par conséquent, votre utilisateur non root ne disposera pas des informations / du contrôle complets sur le processus en cours. Par exemple, il ne pourra pas (dans le cas courant) déterminer quelles connexions appartiennent à l'application via / proc / PID / fd / (netstat -aptn | grep PID).
  • a un désavantage en matière de sécurité: pendant que votre application (ou toute application utilisant les ports 443-1024) est en panne pour une raison quelconque, une autre application peut utiliser le port. Mais ce problème pourrait également être appliqué à CAP / suid (si vous le définissez sur un interpréteur, par exemple java / nodejs) et iptables-redirect. Utilisez la méthode systemd-socket pour exclure ce problème. Utilisez la méthode authbind pour n'autoriser que la liaison utilisateur spéciale.
  • ne nécessite pas la configuration de CAP / suid à chaque fois que vous déployez une nouvelle version de l'application.
  • ne nécessite pas de support / modification d'application, comme la méthode systemd-socket.
  • ne nécessite pas de reconstruction du noyau (si la version en cours supporte ce paramètre sysctl)
  • ne fait pas LD_PRELOAD comme la méthode authbind / privbind, cela pourrait potentiellement affecter les performances, la sécurité, le comportement (n’a-t-il pas été testé). Autrement, authbind est une méthode vraiment flexible et sécurisée.
  • surpasse la méthode REDIRECT / DNAT iptables, car elle ne nécessite ni traduction d'adresse, ni suivi de l'état de la connexion, etc. Cela n'est visible que sur les systèmes à forte charge.

En fonction de la situation, je choisirais entre sysctl, CAP, authbind et iptables-redirect. Et c’est formidable que nous ayons tant d’options.

Au démarrage:

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

Ensuite, vous pouvez vous connecter au port sur lequel vous transférez.

Avec systemd, il vous suffit de modifier légèrement votre service pour accepter les sockets préactivés.

Vous pourrez utiliser ultérieurement l'activation du socket systemd .

Aucune capacité, iptables ou autres astuces ne sont nécessaires.

Il s'agit du contenu des fichiers systemd pertinents de cet exemple de serveur http python

Fichier httpd-true.service

[Unit]
Description=Httpd true 

[Service]
ExecStart=/usr/local/bin/httpd-true
User=subsonic

PrivateTmp=yes

Fichier httpd-true.socket

[Unit]
Description=HTTPD true

[Socket]
ListenStream=80

[Install]
WantedBy=default.target

Il y a aussi la "façon de djb". Vous pouvez utiliser cette méthode pour démarrer votre processus en tant qu'utilisateur root sur n'importe quel port sous tcpserver. Le contrôle du processus sera ensuite confié à l'utilisateur spécifié immédiatement après le démarrage du processus.

#!/bin/sh

UID=`id -u yourusername`
GID=`id -g yourusername`
exec tcpserver -u $UID -g $GID -RHl0 0 portnumber   /path/to/your/process &

Pour plus d'informations, voir: http://thedjbway.b0llix.net/daemontools/uidgid. html

Utilisez l'utilitaire de privbind . : il permet à une application sans privilège de se lier à des ports réservés.

Étant donné que le PO n'est que développement / test, des solutions moins sophistiquées peuvent être utiles:

setcap peut être utilisé sur un interpréteur de script pour attribuer des fonctionnalités à des scripts. Si setcaps sur le binaire d'interprète global n'est pas acceptable, créez une copie locale du fichier binaire (n'importe quel utilisateur peut) et obtenez root pour setcap sur cette copie. Python2 (au moins) fonctionne correctement avec une copie locale de l'interpréteur dans votre arbre de développement de script. Aucun suid n'est nécessaire pour que l'utilisateur root puisse contrôler les fonctionnalités auxquelles les utilisateurs ont accès.

Si vous devez suivre les mises à jour de l'interpréteur à l'échelle du système, utilisez un script shell comme suit pour exécuter votre script:

#!/bin/sh
#
#  Watch for updates to the Python2 interpreter

PRG=python_net_raw
PRG_ORIG=/usr/bin/python2.7

cmp $PRG_ORIG $PRG || {
    echo ""
    echo "***** $PRG_ORIG has been updated *****"
    echo "Run the following commands to refresh $PRG:"
    echo ""
    echo "    $ cp $PRG_ORIG $PRG"
    echo "    # setcap cap_net_raw+ep $PRG"
    echo ""
    exit
}

./$PRG $*

J'ai essayé la méthode iptables PREROUTING REDIRECT. Dans les noyaux plus anciens, il semble que ce type de règle n'ait pas été pris en charge pour IPv6 . Mais apparemment, il est maintenant supporté par ip6tables v1.4.18 et le noyau Linux v3.8.

J'ai également constaté que PREROUTING REDIRECT ne fonctionnait pas pour les connexions initiées dans la machine. Pour utiliser les connexions de la machine locale, ajoutez également une règle OUTPUT - voir la redirection de port iptables ne fonctionnant pas pour localhost . Par exemple. quelque chose comme:

iptables -t nat -I OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

J'ai également constaté que PREROUTING REDIRECT affectait également les paquets transférés . Autrement dit, si la machine transfère également des paquets entre interfaces (par exemple, si elle agit comme un point d’accès Wi-Fi connecté à un réseau Ethernet), la règle iptables intercepte également les connexions des clients connectés aux destinations Internet et les redirige vers la machine. Ce n'est pas ce que je voulais, je voulais seulement rediriger les connexions qui étaient dirigées vers la machine elle-même. J'ai trouvé que je ne pouvais que faire en sorte que les paquets adressés à la boîte soient affectés en ajoutant -m addrtype --dst-type LOCAL . Par exemple. quelque chose comme:

iptables -A PREROUTING -t nat -p tcp --dport 80 -m addrtype --dst-type LOCAL -j REDIRECT --to-port 8080

Une autre possibilité consiste à utiliser le transfert de port TCP. Par exemple. en utilisant socat :

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

Cependant, l’un des inconvénients de cette méthode est que l’application qui écoute sur le port 8080 ne connaît pas l’adresse source des connexions entrantes (par exemple, pour la journalisation ou à des fins d’identification).

Réponse à 2015 / septembre:

ip6tables prend désormais en charge le NAT IPV6: http: // www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt

Vous aurez besoin du noyau 3.7 +

Preuve:

[09:09:23] root@X:~ ip6tables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:80 redir ports 8080
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:443 redir ports 1443

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top