Kann ich eine benutzerspezifische Hosts-Datei erstellen, um / etc / hosts zu ergänzen?

192

Ist es möglich, eine Liste von Hosts hinzuzufügen, die nur für einen bestimmten Benutzer spezifisch sind? Vielleicht eine benutzerspezifische Hosts-Datei?

Dieser Mechanismus sollte auch die Einträge in der /etc/hostsDatei ergänzen .

Redspike
quelle
2
Nun, Sie könnten stattdessen eigene Nameserver ausführen und den Benutzer verschiedene Nameserver pro benutzerspezifischer resolv.conf verwenden lassen - mit der Ausnahme, dass das Erstellen einer benutzerspezifischen resolv.conf genauso schwierig zu sein scheint wie das Erstellen von benutzerspezifischen / etc / hosts.
SF.
2
Wenn der Server remote ist, versuchen Sie es mit der Datei ~ / .ssh / config: this post .
Aaiezza

Antworten:

133

Die von Ihnen gesuchte Funktionalität ist in glibc implementiert. Sie können eine benutzerdefinierte Hostdatei definieren, indem Sie die HOSTALIASESUmgebungsvariable festlegen . Die Namen in dieser Datei werden von übernommen gethostbyname(siehe Dokumentation ).

Beispiel (getestet auf Ubuntu 13.10):

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

Einige Einschränkungen:

  • HOSTALIASESFunktioniert nur für Anwendungen, die getaddrinfo(3)oder verwendengethostbyname(3)
  • Wenn setuid verwendet wird, bereinigt libc die Umgebung, was bedeutet, dass die HOSTALIASESEinstellung verloren geht. ping ist setuid root (da es auf ICMP-Pakete warten muss), HOSTALIASESfunktioniert also nicht mit ping, es sei denn, Sie sind bereits root, bevor Sie ping aufrufen.
pwuertz
quelle
12
Beachten Sie, dass dies nicht funktioniert, wenn Sie nscdHostnamen ohne Punkt verwenden.
Stéphane Chazelas
3
Dies scheint auf CentOS 6
kbolino
3
Spät zur Party, aber das ist das Gegenteil von dem, was gewünscht wird, nicht wahr? Ich denke, OP sucht nach einer ähnlichen Lösung wie das Hinzufügen von Host-auflösenden Einträgen zu / etc / hosts, aber eine, die im Userland ohne eskalierte Berechtigungen durchgeführt werden kann. (ie 127.0.0.1 somedomain.com)
Nuri Hodges
Ich erinnere mich damals nicht, aber heutzutage ist Ping unter Linux keine versteckte Binärdatei. es nutzt Fähigkeiten. Wenn Sie laufen getcap /usr/sbin/pingkönnten Sie sehen so etwas wie: /usr/bin/ping = cap_net_admin,cap_net_raw+p. Und technisch gesehen muss es eher einen Raw-Socket als einen ICMP-Socket öffnen (aber ich nehme an, Sie könnten argumentieren, dass dies nur eine Semantik ist).
Pryftan
Obwohl der Mann sagt "die Alias-Datei, auf die HOSTALIASES zeigt, wird zuerst nach dem Namen gesucht", ist die Priorität zufällig und wenn dieses Beispiel ein Dutzend Mal ausgeführt wird, geht es schief.
Nakilon
42

Neben den LD_PRELOADTricks. Eine einfache Alternative, die auf einigen Systemen funktionieren kann, besteht darin, eine Kopie der Systembibliothek, die die Auflösung von Hostnamen handhabt, binär zu bearbeiten und durch /etc/hostseinen eigenen Pfad zu ersetzen .

Zum Beispiel unter Linux:

Wenn Sie nicht verwenden nscd, kopieren Sie libnss_files.soan einen Ort Ihrer Wahl wie:

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

(Die gemeinsam genutzte Bibliothek kann sich an einer anderen Stelle befinden, z. B. /lib/libnss_files.so.2)

Bearbeiten Sie die Kopie nun binär, um sie durch eine Kopie zu ersetzen /etc/hosts, die der Länge der Kopie entspricht /tmp/hosts.

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

Bearbeiten Sie /tmp/hosts, um den gewünschten Eintrag hinzuzufügen. Und benutze

export LD_LIBRARY_PATH=~/lib

für nss_filesschauen in /tmp/hostsstatt /etc/hosts.

Stattdessen /tmp/hostskönnten Sie es auch machen /dev/fd//3(hier mit zwei Schrägstrichen, so dass die Länge /dev/fd//3der gleiche ist wie die von /etc/hosts) und tun

exec 3< ~/hosts

Zum Beispiel, was es unterschiedlichen Befehlen erlauben würde, unterschiedliche hostsDateien zu verwenden.

Wenn nscdes installiert ist und ausgeführt wird, können Sie es umgehen, indem Sie denselben Trick ausführen, aber diesmal libc.so.6den Pfad zum nscd-Socket (so etwas wie /var/run/nscd/socket) durch einen nicht vorhandenen Pfad ersetzen .

Stéphane Chazelas
quelle
12
+1 für Kühnheit, -1 für den Schockwert
Fche
7
+1 für binäre Patches, -1 für Sicherheitsrisiken
Parthian Shot
@ParthianShot, welche Auswirkungen auf die Sicherheit?
Stéphane Chazelas
1
@ StéphaneChazelas Wenn Sie LD_LIBRARY_PATHauf ein Verzeichnis verweisen, dessen Eigentümer der Benutzer ist, kann jeder andere vom Benutzer ausgeführte Prozess dieses Verzeichnis verwenden, um alle neuen Prozesse zu übernehmen, die durch das Ersetzen von Bibliotheken entstehen. Und Updates libnss_files.soüber den Paketmanager (einschließlich Sicherheitsupdates) werden in der gepatchten Version nicht berücksichtigt. Das Ändern LD_LIBRARY_PATHist im Allgemeinen aus anderen Gründen nicht empfehlenswert, aber aufgrund dieser Probleme auch nicht sinnvoll.
Parthian Shot
13
@ParthianShot, dein Punkt über fehlende Updates ist ein fairer Punkt. Wenn jedoch in Ihrem Namen eine betrügerische Software ausgeführt wird, ist es am wenigsten problematisch, Schreibzugriff auf einen Bereich in $ LD_LIBRARY_PATH zu haben, da bereits Schreibzugriff auf viel schlechtere und zuverlässigere Bereiche wie Ihren besteht .bash *, crontab, .forward und alle Konfigurationsdateien der von Ihnen verwendeten Software (wo es zum Beispiel LD_ {PRELOAD, LIBRARY_PATH} festlegen kann, aber normalerweise viel schlimmer machen würde)
Stéphane Chazelas
24

Private Mountspaces, die mit dem unshareBefehl erstellt wurden, können verwendet werden, um eine private Datei / etc / hosts für einen Shell-Prozess und alle nachfolgenden untergeordneten Prozesse bereitzustellen, die von dieser Shell gestartet werden.

# 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
quelle
3
Warten. Ich dachte, mount mounte gerade Dateisysteme in Verzeichnisse (Mount-Punkte). Ich wusste nicht, dass eine Datei auf eine andere Datei gemountet werden kann. Funktioniert das wirklich (Ich
frage
5
Ja, es funktioniert, Sie können eine Datei mit --bind über eine andere Datei mounten.
Frielp
Nur als Hinweis für Neugierige: Dies hat mit Namespaces zu tun; Es gibt die Syscalls unshare(2)und clone(2)das ist ein Teil der Magie hier. Siehe auch namespaces(7)und user_namespaces(7).
Pryftan
5

Eine Lösung besteht darin, jeden Benutzer in einem eigenen zu haben chroot, sodass jeder für sich einen eigenen Benutzer haben kann /etc/hosts.

Pletiplot
quelle
3
Dies könnte eine Antwort sein, aber wie mit wenig Erklärung angegeben, ist es eher als Kommentar geeignet
Anthon
2
Nun ... ja, es ist machbar. Zwar ist Chrooting eine ziemlich schwere Lösung für diese Art von Dingen. Und bringt seine eigenen Probleme mit sich.
Parthian Shot
5

Ich hatte das gleiche Bedürfnis, also habe ich libnss-userhosts ausprobiert, aber es schlägt bei Multithread-Anwendungen fehl. Deshalb habe ich libnss-homehosts geschrieben . Es ist sehr neu und nur von mir getestet. Sie können eine Chance dafür geben! Es werden einige Optionen in /etc/host.conf, mehrere Aliasnamen und die umgekehrte Auflösung (von Adresse zu Name) unterstützt.

Bandie
quelle
1
Dies scheint eine gute Idee zu sein, sich an die libnss-Betreuer und / oder an die Distributionsbetreuer zu wenden. Zuvor können Benutzer ohne Root-Berechtigung diese Funktion jedoch nicht verwenden. Noch, +1
einpoklum
3

Folgendes einzutragen ~/.bashrcfunktioniert für mich in der Bash. Es konvertiert den Hostnamen im Befehl in eine Adresse, die auf Einträgen in basiert ~/.hosts. Falls ~/.hostsnicht vorhanden oder der Hostname nicht vorhanden ist ~/.hosts, wird der Befehl wie gewohnt ausgeführt. Dies sollte mit den ursprünglichen Flags der relevanten Funktionen funktionieren und unabhängig davon, wo der Hostname relativ zu den Flags platziert ist, z ping -i 0.5 host1 -c 3. B. funktioniert. Die ~/.hostsDatei hat Vorrang vor jedem anderen Speicherort für die Suche nach Hostnamen. Wenn also doppelte Hostnamen vorhanden sind, wird die Adresse in ~/.hostsverwendet.

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

Ein Beispiel für ~/.hostsist unten angegeben. Es folgt dem gleichen Format wie /etc/hosts. Kommentare und Leerzeichen werden korrekt behandelt.

$ 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
quelle
Kann git oder wget diese "Lösung" verwenden? Oder nur Ihre Funktion, die Funktion "auflösen" verwenden?
Qinsi
2

Ich bin mir nicht sicher, ob dies Ihnen helfen würde, aber ich bin hierher gekommen, um nach einer Möglichkeit zu suchen, gespeicherte "Hosts" irgendwo hinzuzufügen, auf die nur mein Benutzer Zugriff hatte.

Ich musste grundsätzlich in der Lage sein, in bestimmte Kästchen in unserem Arbeitsnetzwerk zu sshen, das nur einen Einstiegspunkt hat.

Ich habe meiner .bashrcDatei Aliase hinzugefügt .

Wenn Sie beispielsweise Folgendes hinzugefügt haben:

alias jrfbox='ssh [email protected]' 

am unteren Rand Ihres ~/.bashrc( ~ist Ihr Home-Verzeichnis). Dann , nachdem Sie sich abmelden und erneut anmelden, können Sie geben jrfbox, treffen Enter, und es wird eine Verbindung.

Jason
quelle
14
Wenn Sie speziell im SSH-Fall interessiert sind, sollten Sie sehen man ssh_config.
Nick
1
Sie müssen in wieder nicht abmelden und wieder neu zu laden ~/.bashrc, gehen Sie einfach source ~/.bashrc.
user991710
1
@ user991710 Oder für diese Angelegenheit. ~/.bashrc
Pryftan