Czy mogę utworzyć plik hosts specyficzny dla użytkownika jako uzupełnienie / etc / hosts?


192

Czy można dodać listę hostów specyficznych tylko dla określonego użytkownika? Być może specyficzny dla użytkownika plik hosts?

Mechanizm ten powinien również uzupełniać wpisy w /etc/hostspliku.


2
cóż, możesz zamiast tego uruchomić własne serwery nazw i pozwolić, aby użytkownik używał różnych serwerów nazw dla specyficznego dla użytkownika resolv.conf - z wyjątkiem tworzenia specyficznego dla użytkownika resolv.conf wydaje się być tak samo trudne, jak tworzenie specyficznych dla użytkownika / etc / hosts.
SF.

2
Jeśli serwer jest zdalny, możesz wypróbować plik ~ / .ssh / config: ten post .
aaiezza

Odpowiedzi:


133

Funkcjonalność, której szukasz, została zaimplementowana w glibc. Możesz zdefiniować niestandardowy plik hosts, ustawiając HOSTALIASESzmienną środowiskową. Nazwy w tym pliku zostaną zebrane przez gethostbyname(patrz dokumentacja ).

Przykład (testowany na Ubuntu 13.10):

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

Niektóre ograniczenia:

  • HOSTALIASESdziała tylko dla aplikacji używających getaddrinfo(3)lubgethostbyname(3)
  • Kiedy używa się setuid, libc dezynfekuje środowisko, co oznacza, że HOSTALIASESustawienie zostało utracone. ping jest setuid root (ponieważ musi nasłuchiwać pakietów ICMP), więc HOSTALIASESnie będzie działał z pingiem, chyba że jesteś już rootem przed wywołaniem ping.

12
Pamiętaj, że to nie działa, jeśli używasz nscdi jest ograniczone do nazw hostów bez kropki.
Stéphane Chazelas

3
To nie wydaje się działać na CentOS 6
kbolino

3
Późno na imprezę, ale to jest odwrotność tego, co jest pożądane, prawda? Myślę, że OP szuka podobnego rozwiązania do dodawania pozycji rozdzielających hosty do / etc / hosts, ale takich, które można zrobić w przestrzeni użytkownika bez eskalowanych uprawnień. (tj. 127.0.0.1 somedomain.com)
Nuri Hodges

Nie pamiętam wtedy, ale obecnie ping nie jest sididowym plikiem binarnym w Linuksie; wykorzystuje możliwości. Po uruchomieniu getcap /usr/sbin/pingmożna zobaczyć coś takiego: /usr/bin/ping = cap_net_admin,cap_net_raw+p. I technicznie jest tak, że musi otworzyć surowe gniazdo zamiast ICMP (ale przypuszczam, że można argumentować, że to tylko semantyka).
Pryftan,

Pomimo tego, że mężczyzna mówi, że „plik aliasu wskazany przez HOSTALIASES zostanie najpierw przeszukany w poszukiwaniu nazwy”, priorytet jest losowy i jeśli uruchomimy ten przykładowy wget kilkanaście razy, to się nie powiedzie.
Nakilon

42

Oprócz LD_PRELOADsztuczek. Prostą alternatywą, która może działać na kilku systemach, byłaby edycja binarna kopii biblioteki systemowej, która obsługuje rozpoznawanie nazw hostów w celu zastąpienia ich /etc/hostswłasną ścieżką.

Na przykład w systemie Linux:

Jeśli nie używasz nscd, skopiuj libnss_files.sodo własnej lokalizacji, na przykład:

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

(udostępniona biblioteka może znajdować się w innym miejscu, np. /lib/libnss_files.so.2)

Teraz edytuj kopię binarnie, aby zamienić /etc/hoststam coś na taką samą długość /tmp/hosts.

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

Edytuj, /tmp/hostsaby dodać żądany wpis. I użyć

export LD_LIBRARY_PATH=~/lib

dla nss_filesspojrzeć w /tmp/hostszamiast /etc/hosts.

Zamiast tego /tmp/hostsmożesz to zrobić /dev/fd//3(tutaj, używając dwóch ukośników, aby długość /dev/fd//3była taka sama jak /etc/hosts), i wykonaj

exec 3< ~/hosts

Na przykład, które pozwoliłyby różnym poleceniom korzystać z różnych hostsplików.

Jeśli nscdjest zainstalowany i uruchomiony, możesz go obejść, wykonując tę ​​samą sztuczkę, ale tym razem libc.so.6i zastąp ścieżkę do gniazda nscd (coś podobnego /var/run/nscd/socket) jakąś nieistniejącą ścieżką.


12
+1 za zuchwałość, -1 za wartość szoku
fche

7
+1 za łatanie binarne, -1 za wpływ na bezpieczeństwo
Parthian Shot

@ParthianShot, jakie konsekwencje dla bezpieczeństwa?
Stéphane Chazelas

1
@ StéphaneChazelas Zmiana LD_LIBRARY_PATHwskazania na katalog należący do użytkownika oznacza, że ​​każdy inny proces uruchamiany przez użytkownika może korzystać z tego katalogu, aby dokooptować wszelkie nowe procesy powstałe przez zastąpienie bibliotek. Aktualizacje za libnss_files.sopośrednictwem menedżera pakietów (w tym aktualizacje zabezpieczeń) nie będą odzwierciedlone w poprawionej wersji. Modyfikowanie LD_LIBRARY_PATHjest ogólnie rzecz biorąc złe z innych powodów, ale jest też nierozsądne z powodu tych problemów.
Parthian Shot

13
@ParthianShot, twoja opinia o brakujących aktualizacjach jest słuszna. Jednak z drugiej strony, jeśli nieuczciwe oprogramowanie działa w twoim imieniu, posiadanie dostępu do zapisu do obszaru w $ LD_LIBRARY_PATH byłoby najmniejszym zmartwieniem, ponieważ już ma dostęp do zapisu do znacznie gorszych i bardziej niezawodnych obszarów, takich jak twój .bash *, crontab, .forward i wszystkie pliki konfiguracyjne według całego oprogramowania, którego używasz (gdzie może na przykład ustawić LD_ {PRELOAD, LIBRARY_PATH}, ale zwykle robiłoby to znacznie gorzej)
Stéphane Chazelas

24

Prywatnych obszarów montowania utworzonych za pomocą unsharekomendy można użyć do udostępnienia prywatnego pliku / etc / hosts procesowi powłoki i wszelkim kolejnym procesom potomnym rozpoczynającym się od tej powłoki.

# 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
Czekać. Myślałem, że montujemy właśnie zamontowane systemy plików w katalogach (punkty montowania). Nie wiedziałem, że plik można zamontować na innym pliku. Czy to naprawdę działa? (Pytam o to poważnie. To nie jest sarkazm.)
zabójca

5
Tak, to działa, możesz zamontować plik na innym pliku za pomocą --bind.
frielp

Tak jak uwaga dla ciekawskich: dotyczy to przestrzeni nazw; są systemowe unshare(2)i clone(2)to jest część magii tutaj. Zobacz także namespaces(7)i user_namespaces(7).
Pryftan,

5

Jednym z rozwiązań jest umieszczenie każdego użytkownika w osobnym miejscu chroot, aby każdy mógł mieć oddzielne /etc/hostsdla siebie.


3
To może być odpowiedź, ale jak stwierdzono z niewielkim wyjaśnieniem, bardziej nadaje się jako komentarz
Anthon

2
Cóż ... tak, jest to wykonalne. Chociaż chrooting jest dość wytrzymałym rozwiązaniem dla tego rodzaju rzeczy. I niesie ze sobą własny zestaw problemów.
Parthian Shot

5

Stawiłem czoła tej samej potrzebie, więc wypróbowałem libnss-userhosts, ale nie działa w aplikacjach wielowątkowych. Dlatego napisałem libnss-homehosts . Jest bardzo nowy i przetestowany tylko przeze mnie. Możesz dać temu szansę! Obsługuje niektóre opcje w /etc/host.conf, wiele nazw aliasów i odwrotne rozpoznawanie (adres do nazwy).


1
Wydaje się, że dobrym pomysłem jest kontakt z opiekunami libnss i / lub opiekunami dystrybucji. Ale zanim to nastąpi, użytkownicy bez rootowania nie będą mogli go używać. Mimo to +1
einpoklum

3

Umieszczenie poniższego ~/.bashrcdziała dla mnie w bash. Konwertuje nazwę hosta w poleceniu na adres oparty na wpisach w ~/.hosts. Jeśli ~/.hostsnie istnieje lub nie można znaleźć nazwy hosta ~/.hosts, polecenie jest wykonywane normalnie. Powinno to działać z oryginalnymi flagami odpowiednich funkcji i niezależnie od tego, gdzie nazwa hosta jest umieszczona względem flag, np ping -i 0.5 host1 -c 3. Działa. ~/.hostsPlik ma pierwszeństwo przed każdym innym miejscu na znalezienie nazwy hostów, więc jeśli są jakieś dupicate hostów, adres w ~/.hostszostaną wykorzystane.

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

Przykład ~/.hostspodano poniżej. Ma taki sam format jak /etc/hosts. Komentarze i białe znaki są obsługiwane poprawnie.

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

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

Czy git lub wget mogą użyć tego „rozwiązania”? A może po prostu twoja funkcja, która używa funkcji „rozwiązać”?
Qinsi

2

Nie jestem pewien, czy to by ci pomogło, ale przyszedłem tutaj, aby znaleźć sposób dodania zapisanych „hostów” w miejscu łatwo dostępnym tylko dla mojego użytkownika.

Zasadniczo musiałem móc ssh w niektórych polach w naszej sieci roboczej, która ma tylko jeden punkt wejścia.

Dodałem aliasy do mojego .bashrcpliku.

Na przykład, jeśli dodałeś:

alias jrfbox='ssh jason@192.168.6.6' 

na dole twojego ~/.bashrc( ~jest twoim katalogiem domowym). Następnie po ponownym wylogowaniu i zalogowaniu się możesz pisać jrfbox, naciskać Enter, a nastąpi połączenie.


14
Jeśli interesuje Cię konkretnie sprawa SSH, powinieneś zobaczyć man ssh_config.
Nick

1
Nie musisz się wylogowywać i ponownie logować, aby ponownie załadować ~/.bashrc, po prostu zrób to source ~/.bashrc.
user991710,

1
@ user991710 Albo o to. ~/.bashrc
Pryftan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.