Bisakah saya membuat file host khusus pengguna untuk melengkapi / etc / hosts?

193

Apakah mungkin menambahkan daftar host yang hanya khusus untuk pengguna tertentu? Mungkin file host khusus pengguna?

Mekanisme ini juga harus melengkapi entri dalam /etc/hostsfile.

redspike
sumber
3
baik, Anda mungkin menjalankan nameserver sendiri, dan meminta pengguna menggunakan nameserver berbeda per resolv.conf khusus pengguna - kecuali membuat resolv.conf khusus pengguna tampaknya sama sulitnya dengan membuat spesifik pengguna / etc / hosts.
SF.
2
Jika server jauh, Anda dapat mencoba file ~ / .ssh / config: postingan ini .
aaiezza

Jawaban:

134

Fungsionalitas yang Anda cari diimplementasikan dalam glibc. Anda dapat menentukan file host kustom dengan mengatur HOSTALIASESvariabel lingkungan. Nama-nama dalam file ini akan diambil oleh gethostbyname(lihat dokumentasi ).

Contoh (diuji pada Ubuntu 13.10):

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

Beberapa batasan:

  • HOSTALIASEShanya berfungsi untuk aplikasi yang menggunakan getaddrinfo(3)ataugethostbyname(3)
  • Ketika setuid digunakan libc membersihkan lingkungan, yang berarti bahwa HOSTALIASESpengaturannya hilang. ping adalah setuid root (karena itu perlu mendengarkan paket ICMP), jadi HOSTALIASEStidak akan berfungsi dengan ping kecuali Anda sudah melakukan root sebelum menelepon ping.
pwuertz
sumber
12
Perhatikan bahwa itu tidak berfungsi jika Anda menggunakan nscddan terbatas pada nama host tanpa titik.
Stéphane Chazelas
3
Ini sepertinya tidak bekerja pada CentOS 6
kbolino
3
Terlambat ke pesta, tapi ini kebalikan dari apa yang diinginkan, bukan? Saya pikir OP sedang mencari solusi yang mirip dengan menambahkan entri penyelesaian host ke / etc / hosts, tetapi yang dapat dilakukan di userland tanpa peningkatan hak. (yaitu 127.0.0.1 somedomain.com)
Nuri Hodges
Saya tidak ingat waktu itu tetapi belakangan ini ping bukan binari suid di Linux; menggunakan kemampuan. Jika Anda menjalankan getcap /usr/sbin/pingAnda mungkin melihat sesuatu seperti: /usr/bin/ping = cap_net_admin,cap_net_raw+p. Dan secara teknis itu yang dibutuhkan untuk membuka soket mentah daripada ICMP (tapi saya kira Anda bisa berdebat itu hanya semantik).
Pryftan
1
Meskipun pria itu mengatakan "file alias yang ditunjuk oleh HOSTALIASES pertama kali akan dicari nama" prioritasnya adalah acak dan jika menjalankan contoh wget ini belasan kali itu salah.
Nakilon
43

Di samping LD_PRELOADtrik. Alternatif sederhana yang dapat bekerja pada beberapa sistem adalah dengan mengedit biner pustaka sistem yang menangani resolusi nama host untuk diganti /etc/hostsdengan jalur Anda sendiri.

Misalnya, di Linux:

Jika Anda tidak menggunakan nscd, salin libnss_files.soke beberapa lokasi Anda sendiri seperti:

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

(perpustakaan bersama dapat ditemukan di tempat lain, misalnya /lib/libnss_files.so.2)

Sekarang, edit biner salinan untuk menggantikan /etc/hostsdi sana untuk sesuatu yang sama panjangnya /tmp/hosts.

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

Edit /tmp/hostsuntuk menambahkan entri yang Anda inginkan. Dan gunakan

export LD_LIBRARY_PATH=~/lib

untuk nss_filesmelihat, /tmp/hostsbukan /etc/hosts.

Alih-alih /tmp/hosts, Anda juga bisa membuatnya /dev/fd//3(di sini menggunakan dua garis miring sehingga panjangnya /dev/fd//3sama dengan /etc/hosts), dan lakukan

exec 3< ~/hosts

Misalnya yang akan memungkinkan perintah yang berbeda menggunakan hostsfile yang berbeda .

Jika nscddiinstal dan dijalankan, Anda dapat memotongnya dengan melakukan trik yang sama, tetapi kali ini untuk libc.so.6dan mengganti jalur ke soket nscd (semacamnya /var/run/nscd/socket) dengan beberapa jalur yang tidak ada.

Stéphane Chazelas
sumber
12
+1 untuk keberanian, -1 untuk nilai guncangan
fche
7
+1 untuk penambalan biner, -1 untuk implikasi keamanan
Parthian Shot
@ParthianShot, apa implikasi keamanannya?
Stéphane Chazelas
1
@ StéphaneChazelas Mengubah LD_LIBRARY_PATHke menunjuk ke direktori yang dimiliki oleh pengguna berarti proses lain yang dijalankan oleh pengguna dapat menggunakan direktori itu untuk mengkooptasi proses baru yang dihasilkan dengan mengganti perpustakaan. Dan pembaruan libnss_files.somelalui manajer paket (termasuk pembaruan keamanan) tidak akan tercermin dalam versi yang ditambal. Memodifikasi LD_LIBRARY_PATHumumnya merupakan hal yang buruk untuk direkomendasikan karena alasan lain, tetapi juga tidak bijaksana karena masalah tersebut.
Parthian Shot
13
@ParthianShot, poin Anda tentang pembaruan yang hilang adalah poin yang adil. Namun, untuk poin Anda yang lain, jika perangkat lunak jahat berjalan atas nama Anda, itu memiliki akses tulis ke area dalam $ LD_LIBRARY_PATH akan menjadi yang paling sedikit dari kekhawatiran Anda karena sudah mendapat akses tulis ke area yang jauh lebih buruk dan lebih dapat diandalkan seperti Anda .bash *, crontab, .forward, dan semua file konfigurasi oleh semua perangkat lunak yang Anda gunakan (di mana ia dapat misalnya mengatur LD_ {PRELOAD, LIBRARY_PATH} tetapi biasanya akan jauh lebih buruk)
Stéphane Chazelas
25

Ruang mount pribadi yang dibuat dengan unshareperintah dapat digunakan untuk menyediakan file pribadi / etc / hosts ke proses shell dan proses anak berikutnya dimulai dari shell itu.

# 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
sumber
3
Tunggu. Saya pikir me-mount filesystem yang baru saja dipasang ke direktori (mount points). Saya tidak tahu bahwa suatu file dapat dipasang ke file lain. Apakah itu berhasil? (Saya menanyakan hal itu dengan serius. Itu bukan sarkasme.)
killermist
6
Yap, ini berfungsi, Anda dapat me-mount file di atas file lain dengan --bind.
frielp
1
Sama seperti catatan bagi mereka yang penasaran: ini ada hubungannya dengan ruang nama; ada syscalls unshare(2)dan clone(2)itu adalah bagian dari keajaiban di sini. Lihat juga namespaces(7)dan user_namespaces(7).
Pryftan
6

Salah satu solusinya adalah memiliki masing-masing pengguna secara terpisah chroot, sehingga masing-masing dapat memiliki yang terpisah /etc/hostsuntuk diri mereka sendiri.

Pletiplot
sumber
3
Ini bisa menjadi jawaban, tetapi seperti yang dinyatakan dengan sedikit penjelasan itu lebih cocok sebagai komentar
Anthon
2
Yah ... ya, itu bisa dilakukan. Meskipun chroot adalah solusi tugas yang cukup berat untuk hal semacam ini. Dan membawa seperangkat masalah sendiri.
Parthian Shot
6

Saya menghadapi kebutuhan yang sama, jadi saya mencoba libnss-userhosts, tetapi gagal pada aplikasi multithreaded. Karena itu saya telah menulis libnss-homehosts . Ini sangat baru dan hanya diuji oleh saya. Anda mungkin memberi kesempatan untuk itu! Ini mendukung beberapa opsi di /etc/host.conf, beberapa nama alias, dan penyelesaian terbalik (alamat ke nama).

bandie
sumber
1
Ini sepertinya ide yang bagus untuk melempar ke pengelola libn dan / atau pengelola distribusi. Tetapi sebelum itu terjadi, pengguna tanpa root sendiri tidak akan dapat menggunakannya. Tetap saja, +1
einpoklum
4

Menempatkan berikut ~/.bashrcini bekerja untuk saya di bash. Itu mengubah nama host di perintah menjadi alamat berdasarkan entri di ~/.hosts. Jika ~/.hoststidak ada atau jika nama host tidak ditemukan ~/.hosts, perintah dijalankan seperti biasa. Ini harus bekerja dengan flag asli dari fungsi-fungsi yang relevan dan tidak memiliki tempat di mana nama host ditempatkan relatif terhadap flag, misalnya ping -i 0.5 host1 -c 3, berfungsi. The ~/.hostsberkas mengambil preferensi atas lokasi lain untuk menemukan nama host, jadi jika ada nama host dupicate, alamat di ~/.hostsakan digunakan.

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

Contoh ~/.hostsdiberikan di bawah ini. Ini mengikuti format yang sama dengan /etc/hosts. Komentar dan spasi putih ditangani dengan benar.

$ 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
sumber
Bisakah git atau wget menggunakan "tekad" ini? Atau hanya fungsi Anda yang menggunakan fungsi "tekad"?
Qinsi
2

Tidak yakin apakah ini akan membantu Anda, tetapi saya datang ke sini mencari cara untuk menambahkan "host" yang disimpan di tempat yang mudah diakses hanya oleh pengguna saya.

Saya pada dasarnya perlu untuk ssh ke kotak-kotak tertentu di jaringan kerja kami, yang hanya memiliki satu titik masuk.

Apa yang saya lakukan adalah menambahkan alias ke .bashrcfile saya .

Misalnya, jika Anda menambahkan:

alias jrfbox='ssh [email protected]' 

di bagian bawah Anda ~/.bashrc( ~adalah direktori home Anda). Kemudian setelah Anda keluar dan masuk lagi, Anda bisa mengetik jrfbox, menekan Enter, dan itu akan terhubung.

Jason
sumber
14
Jika Anda menarik secara khusus dalam kasus SSH, Anda akan melihat man ssh_config.
Nick
1
Anda tidak perlu keluar dan kembali lagi untuk memuat ulang ~/.bashrc, cukup lakukan source ~/.bashrc.
user991710
1
@ user991710 Atau dalam hal ini. ~/.bashrc
Pryftan