Puis-je créer un fichier hôtes spécifique à l'utilisateur pour compléter / etc / hosts?

193

Est-il possible d'ajouter une liste d'hôtes uniquement spécifiques à un utilisateur donné? Peut-être un fichier d'hôtes spécifique à l'utilisateur?

Ce mécanisme devrait également compléter les entrées du /etc/hostsfichier.

pic rouge
la source
3
Eh bien, vous pouvez plutôt exécuter vos propres serveurs de noms et demander à l'utilisateur d'utiliser différents serveurs de noms par resolv.conf spécifique à l'utilisateur - sauf que la création de resolv.conf spécifique à l'utilisateur semble être aussi difficile que de créer / etc / hosts spécifique à l'utilisateur.
SF.
2
Si le serveur est distant, vous pouvez essayer le fichier ~ / .ssh / config: this post .
aaiezza

Réponses:

134

La fonctionnalité que vous recherchez est implémentée dans glibc. Vous pouvez définir un fichier d'hôtes personnalisé en définissant la HOSTALIASESvariable d'environnement. Les noms dans ce fichier seront récupérés par gethostbyname(voir documentation ).

Exemple (testé sur Ubuntu 13.10):

$ echo 'g www.google.com' >> ~/.hosts
$ export HOSTALIASES=~/.hosts
$ wget g -O /dev/null

Quelques limitations:

  • HOSTALIASESne fonctionne que pour les applications utilisant getaddrinfo(3)ougethostbyname(3)
  • Lorsque setuid est utilisé, libc désinfecte l'environnement, ce qui signifie que le HOSTALIASESparamètre est perdu. ping est setuid root (car il doit écouter les paquets ICMP), il HOSTALIASESne fonctionnera donc pas avec ping sauf si vous êtes déjà root avant d'appeler ping.
Pwuertz
la source
12
Notez que cela ne fonctionne pas si vous utilisez nscdet est limité aux noms d’hôte sans point.
Stéphane Chazelas
3
Cela ne semble pas fonctionner sur CentOS 6
kbolino
3
En retard pour le parti, mais c'est l'inverse de ce qui est désiré, n'est-ce pas? Je pense que OP recherche une solution similaire pour l’ajout d’entrées permettant de résoudre le problème des hôtes dans / etc / hosts, mais qui peut être réalisée à partir de l’utilisateur sans privilèges accrus. (c.-à-d. 127.0.0.1 somedomain.com)
Nuri Hodges
Je ne me souviens pas alors, mais ces jours-ci, ping n'est pas un binaire suid sous Linux; il utilise des capacités. Si vous exécutez getcap /usr/sbin/pingvous pouvez voir quelque chose comme: /usr/bin/ping = cap_net_admin,cap_net_raw+p. Et techniquement, il faut ouvrir une socket raw plutôt que ICMP (mais je suppose que vous pourriez soutenir que ce n’est que de la sémantique).
Pryftan
1
Bien que l'homme dise "le fichier de pseudonyme pointé par HOSTALIASES sera tout d'abord recherché pour le nom", la priorité est aléatoire et, si cet exemple est exécuté, une erreur se produit une douzaine de fois.
Nakilon
43

À côté des LD_PRELOADastuces. Une alternative simple pouvant fonctionner sur quelques systèmes serait d'éditer, en binaire, une copie de la bibliothèque système qui gère la résolution du nom d'hôte afin de la remplacer /etc/hostspar votre propre chemin.

Par exemple, sous Linux:

Si vous ne l'utilisez pas nscd, copiez-le libnss_files.sodans un emplacement de votre choix, par exemple:

mkdir -p -- ~/lib &&
cp /lib/x86_64-linux-gnu/libnss_files.so.2 ~/lib

(la bibliothèque partagée peut être située ailleurs, par exemple /lib/libnss_files.so.2)

Maintenant, éditez binaire la copie pour la remplacer /etc/hostspar quelque chose de la même longueur /tmp/hosts.

perl -pi -e 's:/etc/hosts:/tmp/hosts:g' ~/lib/libnss_files.so.2

Modifier /tmp/hostspour ajouter l'entrée souhaitée. Et utilise

export LD_LIBRARY_PATH=~/lib

pour nss_filesregarder au /tmp/hostslieu de /etc/hosts.

Au lieu de /tmp/hosts, vous pouvez aussi le faire /dev/fd//3(ici, en utilisant deux barres obliques pour que la longueur de /dev/fd//3soit la même que celle de /etc/hosts), et ne

exec 3< ~/hosts

Par exemple, cela permettrait à différentes commandes d'utiliser différents hostsfichiers.

Si nscdest installé et en cours d'exécution, vous pouvez le contourner en procédant de la même manière, mais cette fois pour libc.so.6et remplacez le chemin d'accès à la socket nscd (quelque chose comme /var/run/nscd/socket) par un chemin inexistant.

Stéphane Chazelas
la source
12
+1 pour l'audace, -1 pour la valeur de choc
fche
7
+1 pour le correctif binaire, -1 pour les problèmes de sécurité
Parthian Shot
@ParthianShot, quelles implications pour la sécurité?
Stéphane Chazelas
1
@ StéphaneChazelas Changer LD_LIBRARY_PATHde pointage vers un répertoire appartenant à l'utilisateur signifie que tout autre processus exécuté par l'utilisateur peut utiliser ce répertoire pour coopter tout nouveau processus généré par le remplacement de bibliothèques. Et les mises à jour libnss_files.sovia le gestionnaire de paquets (y compris les mises à jour de sécurité) ne seront pas reflétées dans la version corrigée. La modification LD_LIBRARY_PATHest généralement une mauvaise chose à recommander pour d'autres raisons, mais elle est également déconseillée à cause de ces problèmes.
Parthian Shot
13
@ParthianShot, votre remarque sur les mises à jour manquantes est juste. Cependant, pour votre autre argument, si un logiciel malicieux s'exécute en votre nom, disposer d'un accès en écriture à une zone située dans $ LD_LIBRARY_PATH serait le moindre de vos soucis, car il dispose déjà d'un accès en écriture à des zones bien pires et plus fiables telles que la vôtre. .bash *, crontab, .forward, et tous les fichiers de configuration de tous les logiciels que vous utilisez (où il peut par exemple définir LD_ {PRELOAD, LIBRARY_PATH} mais ferait bien pire)
Stéphane Chazelas le
25

Les espaces de montage privés créés avec la unsharecommande peuvent être utilisés pour fournir un fichier privé / etc / hosts à un processus shell et à tous les processus enfants ultérieurs démarrés à partir de ce shell.

# Start by creating your custom /etc/hosts file
[user] cd ~
[user] cat >my_hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1 news.bbc.co.uk
EOF

[user] sudo unshare --mount
# We're now running as root in a private mountspace. 
# Any filesystem mounts performed in this private mountspace
# are private to this shell process and its children

# Use a bind mount to install our custom hosts file over /etc/hosts
[root] mount my_hosts /etc/hosts --bind

[root] cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1 news.bbc.co.uk

[root] exec su - appuser

[appuser] # Run your app here that needs a custom /etc/hosts file

[appuser] ping news.bbc.co.uk
PING news.bbc.co.uk (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.026 ms
^C
--- news.bbc.co.uk ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.026/0.044/0.062/0.018 ms
frielp
la source
3
Attendez. Je pensais que monter simplement des systèmes de fichiers montés sur des répertoires (points de montage). Je ne savais pas qu'un fichier pouvait être monté sur un autre fichier. Est-ce que ça marche vraiment? (Je demande cela sérieusement. Ce n'est pas un sarcasme.)
Killermist
6
Oui, cela fonctionne, vous pouvez monter un fichier sur un autre fichier avec --bind.
frielp
1
Juste pour les curieux: cela concerne les espaces de noms; il y a les appels système unshare(2)et clone(2)cela fait partie de la magie ici. Voir aussi namespaces(7)et user_namespaces(7).
Pryftan
6

Une solution consiste à placer chaque utilisateur de manière distincte chroot, de manière à ce que chacun puisse avoir sa propre /etc/hostsidentité.

Pletiplot
la source
3
Cela pourrait être une réponse, mais comme indiqué avec peu d'explications, il est plus approprié comme commentaire
Anthon
2
Eh bien ... oui, c'est faisable. Bien que le chrootage soit une solution assez lourde pour ce genre de chose. Et apporte avec lui son propre ensemble de problèmes.
Parthian Shot
6

J'ai rencontré le même besoin, j'ai donc essayé libnss-userhosts, mais cela échouait dans les applications multithread. Par conséquent, j'ai écrit libnss-homehosts . C'est très nouveau et testé seulement par moi. Vous pouvez donner une chance pour cela! Il prend en charge certaines options de /etc/host.conf, plusieurs noms d’alias et la résolution inverse (adresse à nom).

bandie
la source
1
Cela semble être une bonne idée de faire un discours auprès des mainteneurs de libnss et / ou des mainteneurs de distribution. Mais avant que cela ne se produise, les utilisateurs sans racine eux-mêmes ne pourront pas l'utiliser. Toujours, +1
einpoklum
4

Placer les éléments suivants dans ~/.bashrcfonctionne pour moi en bash. Il convertit le nom d'hôte de la commande en une adresse basée sur les entrées de ~/.hosts. S'il ~/.hostsn'existe pas ou si le nom d'hôte est introuvable ~/.hosts, la commande s'exécute normalement. Cela devrait fonctionner avec les indicateurs d'origine des fonctions pertinentes et sans indiquer l'emplacement où le nom d'hôte est placé par rapport aux indicateurs, par exemple ping -i 0.5 host1 -c 3, travaux. Le ~/.hostsfichier a la préférence sur tout autre emplacement pour la recherche de noms d’hôte. Ainsi, s’il existe des noms d’hôte doubles, l’adresse ~/.hostssera utilisée.

$ cat ~/.bashrc 
function resolve {
        hostfile=~/.hosts
        if [[ -f "$hostfile" ]]; then
                for arg in $(seq 1 $#); do
                        if [[ "${!arg:0:1}" != "-" ]]; then
                                ip=$(sed -n -e "/^\s*\(\#.*\|\)$/d" -e "/\<${!arg}\>/{s;^\s*\(\S*\)\s*.*$;\1;p;q}" "$hostfile")
                                if [[ -n "$ip" ]]; then
                                        command "${FUNCNAME[1]}" "${@:1:$(($arg-1))}" "$ip" "${@:$(($arg+1)):$#}"
                                        return
                                fi
                        fi
                done
        fi
        command "${FUNCNAME[1]}" "$@"
}

function ping {
        resolve "$@"
}

function traceroute {
        resolve "$@"
}

Un exemple de ~/.hostsest donné ci-dessous. Il suit le même format que /etc/hosts. Les commentaires et les espaces sont gérés correctement.

$ cat ~/.hosts 
# addresses and hostnames
stackexchange.com se

192.168.0.1 host1 # this is host1's address
login-node.inst.ac.uk login
Kyle Fernandes
la source
Est-ce que git ou wget peut utiliser cette "résolution"? Ou simplement votre fonction qui utilise la fonction "résoudre"?
Qinsi le
2

Je ne suis pas sûr que cela puisse vous aider, mais je suis venu ici pour trouver un moyen d'ajouter des "hôtes" enregistrés dans un endroit facilement accessible à l'utilisateur.

En gros, je devais être capable de ssh dans certaines boîtes de notre réseau de travail, qui n’avait qu’un seul point d’entrée.

Ce que j'ai fait a été d'ajouter des alias à mon .bashrcfichier.

Par exemple, si vous avez ajouté:

alias jrfbox='ssh [email protected]' 

au bas de votre ~/.bashrc( ~est votre répertoire personnel). Ensuite, après vous être déconnecté et reconnecté, vous pouvez taper jrfbox, cliquer Enteret il se connectera.

Jason
la source
14
Si vous êtes particulièrement intéressé par SSH, vous devriez le voir man ssh_config.
Nick
1
Vous n'avez pas besoin de vous déconnecter et de vous reconnecter pour recharger ~/.bashrc, il vous suffit de le faire source ~/.bashrc.
user991710
1
@ user991710 Ou à ce sujet. ~/.bashrc
Pryftan