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.