Чи можу я створити специфічний для користувача файл хостів для доповнення / etc / hosts?


192

Чи можна додати список хостів, специфічний лише для певного користувача? Можливо певний користувачем файл хостів?

Цей механізм також повинен доповнювати записи у /etc/hostsфайлі.


2
Добре, ви можете замість цього запустити власні сервери імен та дозволити користувачеві використовувати різні сервери імен на конкретний користувач resolutionv.conf - за винятком того, що створення резолюції.conf для конкретного користувача виявляється таким же складним, як і створення конкретного користувача / etc / hosts.
СФ.

2
Якщо сервер віддалений, ви можете спробувати файл ~ / .ssh / config: це повідомлення .
aaiezza

Відповіді:


133

Функціонал, який ви шукаєте, реалізований у glibc. Ви можете визначити спеціальний файл хостів, встановивши HOSTALIASESзмінну середовища. Імена цього файлу будуть обрані gethostbyname(див. Документацію ).

Приклад (тестований на Ubuntu 13.10):

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

Деякі обмеження:

  • HOSTALIASESпрацює лише для програм, що використовують getaddrinfo(3)абоgethostbyname(3)
  • При застосуванні setuid libc очищає навколишнє середовище, а це означає, що HOSTALIASESналаштування втрачено. ping - це встановлений корінь (тому що йому потрібно слухати пакети ICMP), тому HOSTALIASESвін не працюватиме з ping, якщо ви вже не root перед тим, як викликати ping.

12
Зауважте, що він не працює, якщо ви використовуєте nscdі обмежений іменами хостів без крапки.
Стефан Шазелас

3
Схоже, це не працює на CentOS 6
kbolino

3
Пізно до вечірки, але це зворотне бажане, чи не так? Я думаю, що ОП шукає подібне рішення для додавання записів, що вирішують хост, до / etc / hosts, але таке, що можна зробити в користувальницькій області без нарощування привілеїв. (тобто 127.0.0.1 somedomain.com)
Нурі Ходжес

Я не пам'ятаю тоді, але в наші дні ping не є бінарним файлом в Linux; він використовує можливості. При запуску getcap /usr/sbin/pingви можете побачити що - щось на кшталт: /usr/bin/ping = cap_net_admin,cap_net_raw+p. А технічно це те, що для цього потрібно відкрити необроблений сокет, а не ICMP (але, мабуть, ви можете стверджувати, що це просто семантика).
Прифтан

Незважаючи на те, що людина каже, що "файл псевдоніму, на який вказують HOSTALIASES, спочатку буде шукати ім'я", пріоритет є випадковим, і якщо запустити цей приклад wget десяток разів, він піде не так.
Накілон

42

Поруч з LD_PRELOADхитрощами. Найпростішою альтернативою, яка може працювати в декількох системах, буде бінарне редагування копії системної бібліотеки, яка обробляє роздільну здатність імені хоста, замінити /etc/hostsна власний шлях.

Наприклад, в Linux:

Якщо ви не використовуєте nscd, скопіюйте libnss_files.soв якесь власне місцеположення, як-от:

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

(спільна бібліотека може знаходитися в іншому місці, наприклад /lib/libnss_files.so.2)

Тепер, бінарне редагування копії, щоб замінити /etc/hostsтам щось на зразок такої довжини, як /tmp/hosts.

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

Редагувати, /tmp/hostsщоб додати потрібну запис. І використовувати

export LD_LIBRARY_PATH=~/lib

для того, nss_filesщоб шукати /tmp/hostsзамість /etc/hosts.

Замість цього /tmp/hosts, ви також можете зробити це /dev/fd//3(тут, використовуючи два косої риски, щоб довжина /dev/fd//3була такою ж, як у /etc/hosts), і зробити

exec 3< ~/hosts

Наприклад, яка дозволила б різним командам використовувати різні hostsфайли.

Якщо nscdвін встановлений і запущений, його можна обійти, виконавши той самий трюк, але на цей раз libc.so.6і замініть шлях до сокета nscd (щось подібне /var/run/nscd/socket) на якийсь неіснуючий шлях.


12
+1 для сміливості, -1 для значення шоку
fche

7
+1 для бінарного виправлення, -1 для наслідків для безпеки
Parthian Shot

@ParthianShot, які наслідки для безпеки?
Стефан Шазелас

1
@ StéphaneChazelas Змінення LD_LIBRARY_PATHвказівки на каталог, що належить користувачеві, означає, що будь-який інший процес, керований користувачем, може використовувати цей каталог для кооптування будь-яких нових процесів, породжених заміною бібліотек. І оновлення libnss_files.soчерез менеджер пакунків (включаючи оновлення безпеки) не відображатимуться у виправленій версії. Зміна, LD_LIBRARY_PATHяк правило, погано рекомендувати з інших причин, але це також нерозумно через ці проблеми.
Парфянський розстріл

13
@ParthianShot, ваша думка щодо відсутніх оновлень є справедливим моментом. Однак для вашого іншого пункту, якщо програмне забезпечення, що працює на вашому імені, працює з програмним забезпеченням, його доступ до запису до області в $ LD_LIBRARY_PATH був би найменшим з ваших турбот, оскільки він уже має доступ до запису в набагато гірші та надійніші сфери, наприклад, як ваш .bash *, кронтаб, .forward, і всі конфігураційні файли по всьому програмному забезпеченню ви використовуєте (де він може, наприклад , встановити LD_ {преднагрузки, library_path} , але , як правило , буде зробити набагато гірше)
Stéphane Chazelas

24

Приватні простори монтажу, створені за допомогою unshareкоманди, можуть використовуватися для надання приватного файлу / etc / hosts процесу оболонки та будь-яких подальших дочірніх процесів, запущених з цієї оболонки.

# 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
Зачекайте. Я думав, монтуйте щойно встановлені файлові системи на каталоги (точки монтажу). Я не знав, що файл може бути встановлений на інший файл. Це справді працює? (Я прошу це серйозно. Це не сарказм.)
вбивця

5
Так, це працює, ви можете встановити файл над іншим файлом за допомогою --bind.
frielp

Як зауваження до цікавих: це стосується просторів імен; є систематичні дзвінки, unshare(2)і clone(2)це є частиною магії. Дивіться також namespaces(7)і user_namespaces(7).
Прифтан

5

Одне рішення - мати кожного користувача окремо chroot, тому кожен може мати окремий /etc/hostsдля себе.


3
Це може бути відповіддю, але як сказано з невеликим поясненням, воно більше підходить як коментар
Антон

2
Ну ... так, це можливо. Хоча хротування - досить важке рішення для подібних речей. І приносить із собою свій набір питань.
Парфянський розстріл

5

Я зіткнувся з такою ж потребою, тому спробував libnss-userhosts, але це не вдається при багатопотокових програмах. Тому я написав лібни-домовики . Це дуже нове і перевірене лише мною. Ви можете дати шанс на це! Він підтримує деякі параметри в /etc/host.conf, декілька імен псевдонімів та зворотного дозволу (адреса до імені).


1
Це здається гарною ідеєю звертатися до обслуговуючого персоналу лібнів та / або до сервісів розповсюдження. Але перш ніж це станеться, користувачі без кореня самі не зможуть ним користуватися. І все-таки +1
einpoklum

3

Розміщення наступного в ~/.bashrcмені працює в баш. Він перетворює ім'я хоста в команді в адресу на основі записів в ~/.hosts. Якщо ~/.hostsйого немає або якщо ім'я хоста неможливо знайти ~/.hosts, команда виконується як звичайне. Це повинно працювати з оригінальними прапорами відповідних функцій і незалежно від того, де ім'я хоста розміщено відносно прапорів, наприклад ping -i 0.5 host1 -c 3, працює. ~/.hostsФайл віддається перевага перед будь-яким іншим місцем для знаходження хостів, так що якщо є якісь - dupicate імен хостів, адреса в ~/.hostsвикористовуватиметься.

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

Приклад ~/.hostsнаведено нижче. Він має той самий формат, що і /etc/hosts. Простір коментарів і пробілів обробляється правильно.

$ 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 або Wget використовувати це "рішення"? Або просто ваші функції, які використовують функцію "вирішити"?
Qinsi

2

Не впевнений, чи допоможе це вам, але я прийшов сюди шукати спосіб додати збережені "хости" десь, які були легко доступні лише моєму користувачеві.

Мені в основному потрібно було мати змогу зайти в певні поля в нашій робочій мережі, де є лише одна точка входу.

Що я зробив, це додати псевдоніми до мого .bashrcфайлу.

Наприклад, якщо ви додали:

alias jrfbox='ssh jason@192.168.6.6' 

внизу вашого домашнього каталогу ~/.bashrc( ~це ваш домашній каталог). Потім після входу та входу знову можна ввести jrfbox, натиснути Enter, і він підключиться.


14
Якщо вам цікаво конкретно у випадку SSH, ви повинні побачити man ssh_config.
Нік

1
Вам не потрібно виходити і знову входити, щоб перезавантажити ~/.bashrc, просто зробіть це source ~/.bashrc.
user991710

1
@ user991710 Або з цього приводу. ~/.bashrc
Прифтан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.