Posso creare un file hosts specifico dell'utente per integrare / etc / hosts?


193

È possibile aggiungere un elenco di host specifici solo per un determinato utente? Forse un file host specifico dell'utente?

Questo meccanismo dovrebbe anche integrare le voci nel /etc/hostsfile.


3
bene, potresti invece eseguire i propri server dei nomi e far sì che l'utente utilizzi server dei nomi diversi per ogni resolv.conf specifico dell'utente - tranne per il fatto che la creazione di un resolv.conf specifico dell'utente sembra essere esattamente difficile quanto la creazione di / etc / hosts specifici dell'utente.
SF.

2
Se il server è remoto, potresti provare il file ~ / .ssh / config: questo post .
aaiezza,

Risposte:


134

La funzionalità che stai cercando è implementata in glibc. È possibile definire un file host personalizzato impostando la HOSTALIASESvariabile di ambiente. I nomi in questo file saranno raccolti da gethostbyname(vedi documentazione ).

Esempio (testato su Ubuntu 13.10):

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

Alcune limitazioni:

  • HOSTALIASESfunziona solo per le applicazioni che utilizzano getaddrinfo(3)ogethostbyname(3)
  • Quando viene usato setuid libc disinfetta l'ambiente, il che significa che l' HOSTALIASESimpostazione è persa. ping è setuid root (perché deve ascoltare i pacchetti ICMP), quindi HOSTALIASESnon funzionerà con ping a meno che tu non sia già root prima di chiamarlo.

12
Si noti che non funziona se si utilizza nscded è limitato ai nomi host senza punto.
Stéphane Chazelas,

3
Questo non sembra funzionare su CentOS 6
kbolino il

3
In ritardo alla festa, ma questo è l'inverso di ciò che si desidera, non è vero? Penso che OP stia cercando una soluzione simile per aggiungere voci che risolvono l'host a / etc / hosts, ma che può essere fatto in userland senza privilegi di escalation. (ie 127.0.0.1 somedomain.com)
Nuri Hodges,

Non ricordo allora, ma oggigiorno il ping non è un binario suid in Linux; usa le capacità. Se si esegue getcap /usr/sbin/pingsi potrebbe vedere qualcosa di simile: /usr/bin/ping = cap_net_admin,cap_net_raw+p. E tecnicamente è che ha bisogno di aprire un socket raw anziché ICMP (ma suppongo che potresti sostenere che è solo una semantica).
Pryftan,

1
Nonostante l'uomo dice "il file alias indicato da HOSTALIASES verrà prima cercato per nome" la priorità è casuale e se si esegue questo esempio di wget una dozzina di volte va storto.
Nakilon,

43

Accanto ai LD_PRELOADtrucchi. Una semplice alternativa che potrebbe funzionare su alcuni sistemi sarebbe quella di modificare binariamente una copia della libreria di sistema che gestisce la risoluzione del nome host per sostituirla /etc/hostscon un percorso personale.

Ad esempio, su Linux:

Se non lo stai usando nscd, copia libnss_files.soin una tua posizione come:

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

(la libreria condivisa può trovarsi altrove, ad es. /lib/libnss_files.so.2)

Ora, modifica binaria la copia per sostituirla /etc/hostscon qualcosa della stessa lunghezza /tmp/hosts.

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

Modifica /tmp/hostsper aggiungere la voce desiderata. E usare

export LD_LIBRARY_PATH=~/lib

per nss_filescercare /tmp/hostsinvece di /etc/hosts.

Invece di /tmp/hosts, potresti anche farlo /dev/fd//3(qui usando due barre in modo che la lunghezza di /dev/fd//3sia la stessa di quella di /etc/hosts), e fai

exec 3< ~/hosts

Ad esempio, ciò consentirebbe a comandi diversi di utilizzare hostsfile diversi .

Se nscdè installato e in esecuzione, puoi bypassarlo facendo lo stesso trucco, ma questa volta per libc.so.6e sostituire il percorso al socket nscd (qualcosa di simile /var/run/nscd/socket) con un percorso inesistente.


12
+1 per audacia, -1 per il valore di shock
fche

7
+1 per patch binarie, -1 per implicazioni di sicurezza
Parthian Shot

@ParthianShot, quali implicazioni per la sicurezza?
Stéphane Chazelas,

1
@ StéphaneChazelas Passare LD_LIBRARY_PATHa una directory di proprietà dell'utente significa che qualsiasi altro processo eseguito dall'utente può utilizzare quella directory per cooptare qualsiasi nuovo processo generato sostituendo le librerie. E gli aggiornamenti libnss_files.sotramite il gestore pacchetti (inclusi gli aggiornamenti di sicurezza) non si rifletteranno nella versione patchata. La modifica LD_LIBRARY_PATHè generalmente una cosa negativa da raccomandare per altri motivi, ma è anche poco saggia a causa di questi problemi.
Parthian Shot,

13
@ParthianShot, il tuo punto sugli aggiornamenti mancanti è un punto giusto. Tuttavia, per l'altro punto, se un software canaglia è in esecuzione a tuo nome, avere accesso in scrittura a un'area in $ LD_LIBRARY_PATH sarebbe il minimo dei tuoi problemi in quanto ha già accesso in scrittura ad aree molto peggiori e più affidabili come la tua .bash *, crontab, .forward e tutti i file di configurazione di tutto il software utilizzato (dove ad esempio può impostare LD_ {PRELOAD, LIBRARY_PATH} ma in genere farebbe molto peggio)
Stéphane Chazelas,

25

Gli spazi di montaggio privati ​​creati con il unsharecomando possono essere utilizzati per fornire un file privato / etc / hosts a un processo di shell e tutti i successivi processi figlio avviati da quella 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

3
Aspettare. Pensavo che mount avesse appena montato filesystem su directory (mount points). Non sapevo che un file potesse essere montato su un altro file. Funziona davvero? (Lo sto chiedendo seriamente. Questo non è sarcasmo.)
Assassino

6
Sì, funziona, puoi montare un file su un altro file con --bind.
martedì

1
Proprio come una nota per i curiosi: questo ha a che fare con gli spazi dei nomi; ci sono i syscalls unshare(2)e clone(2)questo fa parte della magia qui. Vedi anche namespaces(7)e user_namespaces(7).
Pryftan,

6

Una soluzione è quella di avere ciascun utente in un separato chroot, in modo che ciascuno di essi possa avere un separato /etc/hostsper sé.


3
Questa potrebbe essere una risposta, ma come affermato con poche spiegazioni è più adatto come commento
Anthon,

2
Beh ... sì, è fattibile. Anche se il chrooting è una soluzione piuttosto pesante per questo tipo di cose. E porta con sé una serie di problemi.
Parthian Shot,

6

Ho affrontato la stessa necessità, quindi ho provato libnss-userhosts, ma fallisce nelle applicazioni multithread. Pertanto ho scritto libnss-homehosts . È molto nuovo e testato solo da me. Puoi dargli una possibilità! Supporta alcune opzioni in /etc/host.conf, più nomi di alias e risoluzione inversa (indirizzo per nome).


1
Questa sembra una buona idea presentare ai manutentori di libnss e / o ai manutentori della distribuzione. Ma prima che ciò accada, gli utenti senza root non saranno in grado di usarlo. Ancora, +1
einpoklum,

4

Posizionare quanto segue ~/.bashrcfunziona per me in bash. Converte il nome host nel comando in un indirizzo basato sulle voci in ~/.hosts. Se ~/.hostsnon esiste o se non è possibile trovare il nome host ~/.hosts, il comando viene eseguito normalmente. Questo dovrebbe funzionare con i flag originali delle funzioni pertinenti e senza regar di dove si trova il nome host rispetto ai flag, ad esempio ping -i 0.5 host1 -c 3, funziona. Il ~/.hostsfile preferisce qualsiasi altra posizione per trovare i nomi host, quindi se ci sono nomi host duplicati, ~/.hostsverrà utilizzato l'indirizzo in .

$ 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 "$@"
}

Di ~/.hostsseguito è riportato un esempio di . Segue lo stesso formato di /etc/hosts. Commenti e spazi bianchi sono gestiti correttamente.

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

192.168.0.1 host1 # this is host1's address
login-node.inst.ac.uk login

Git o wget possono usare questa "risoluzione"? O solo la tua funzione che usa la funzione "risolvi"?
Qinsi

2

Non sono sicuro che questo possa aiutarti, ma sono venuto qui alla ricerca di un modo per aggiungere "host" salvati da qualche parte che fosse facilmente accessibile solo al mio utente.

Fondamentalmente avevo bisogno di essere in grado di accedere a determinate caselle sulla nostra rete di lavoro, che ha solo un punto di accesso.

Quello che ho fatto è stato aggiungere alias al mio .bashrcfile.

Ad esempio, se hai aggiunto:

alias jrfbox='ssh jason@192.168.6.6' 

in fondo alla tua ~/.bashrc( ~è la tua home directory). Quindi dopo aver effettuato il logout e di nuovo l'accesso, è possibile digitare jrfbox, premere Entere si connetterà.


14
Se sei interessante nello specifico nel caso SSH, dovresti vedere man ssh_config.
Nick,

1
Non è necessario disconnettersi e riconnettersi per ricaricare ~/.bashrc, semplicemente source ~/.bashrc.
user991710

1
@ user991710 O del resto. ~/.bashrc
Pryftan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.