我可以创建用户特定的主机文件来补充/ etc / hosts吗?


192

是否可以添加仅特定于某个用户的主机列表?也许是特定于用户的主机文件?

此机制还应补充/etc/hosts文件中的条目。


2
好吧,您可以改为运行自己的名称服务器,并让用户针对每个特定于用户的resolv.conf使用不同的名称服务器-除了创建特定于用户的resolv.conf似乎与制作特定于用户的/ etc / hosts一样困难。
SF。

2
如果服务器是远程服务器,则可以尝试〜/ .ssh / config文件:本文
aaiezza

Answers:


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是setuid root(因为它需要侦听ICMP数据包),因此HOSTALIASES,除非您在调用ping之前已经是root用户,否则ping无法使用。

12
请注意,如果您正在使用它,它将不起作用nscd,并且仅限于没有点的主机名。
斯特凡Chazelas

3
这在CentOS 6上似乎不起作用
kbolino

3
晚了晚会,但这与期望相反,不是吗?我认为OP正在寻找一种类似的解决方案,以将主机解析项添加到/ etc / hosts中,但是可以在用户级完成而无需提升特权。(即127.0.0.1 somedomain.com
Nuri Hodges

我当时不记得了,但是现在ping并不是Linux中的suid二进制文件。它使用功能。如果您运行getcap /usr/sbin/ping,可能会看到类似:的信息/usr/bin/ping = cap_net_admin,cap_net_raw+p。从技术上讲,它需要打开一个原始套接字而不是ICMP(但我想您可以说这只是语义)。
Pryftan

尽管有人说“将首先搜索HOSTALIASES指向的别名文件”,但是优先级是随机的,如果运行此wget示例多次,它将出错。
Nakilon

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
胆量

7
+1表示二进制补丁,-1表示安全性
Parthian Shot

@ParthianShot,对安全性有何影响?
斯特凡Chazelas

1
@StéphaneChazelas更改LD_LIBRARY_PATH为指向用户拥有的目录意味着用户运行的任何其他进程可以使用该目录来选择通过替换库产生的任何新进程。和更新libnss_files.so通过包管理器(包括安全更新)将不会反映在修补版本。LD_LIBRARY_PATH出于其他原因,建议修改通常是一件坏事,但由于这些问题,这也是不明智的。
Parthian Shot

13
@ParthianShot,关于缺少更新的观点很合理。但是,对于您的另一点,如果恶意软件以您的名义运行,则对$ LD_LIBRARY_PATH中某个区域的写访问权限将是您的后顾之忧,因为它已经具有对更糟糕和更可靠的区域(如您的计算机)的写访问权限.bash *,crontab中,的.forward,和所有软件的所有配置文件使用(它例如可以设置LD_ {预紧力,LIBRARY_PATH}但通常会做的差了很多)
斯特凡Chazelas

24

使用该unshare命令创建的专用装载空间可用于向Shell进程以及从该Shell启动的任何后续子进程提供私有/ 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
等待。我以为mount只是将文件系统装载到目录(装载点)上。我不知道一个文件可以挂载到另一个文件上。这真的有用吗?(我是在认真问这个。这不是在讽刺。)
杀手主义者

5
是的,它可以工作,您可以使用--bind将文件挂载到另一个文件上。
frielp

就像对那些好奇的人的说明:这与名称空间有关;有系统调用unshare(2)clone(2)这是这里魔术的一部分。另请参阅namespaces(7)user_namespaces(7)
Pryftan

5

一种解决方案是将每个用户都放在一个单独的chroot,这样他们每个人都/etc/hosts可以自己拥有一个单独的。


3
这可能是一个答案,但正如很少解释的那样,它更适合作为评论
Anthon

2
好吧...是的,这是可行的。尽管chrooting是解决此类问题的非常繁重的解决方案。并带来了自己的问题。
Parthian Shot

5

我遇到了同样的需求,所以我尝试了libnss-userhosts,但是在多线程应用程序上失败了。因此,我写了libnss-homehosts。这是很新的,只有我自己测试过。您可以为此机会!它支持/etc/host.conf中的某些选项,多个别名和反向解析(地址到名称)。


1
向libnss维护者和/或发行维护者推销似乎是一个好主意。但是在此之前,没有root用户的用户将无法使用它。还是+1
einpoklum

3

将以下内容~/.bashrc放在bash中对我有用。它将根据中的条目将命令中的主机名转换为地址~/.hosts。如果~/.hosts不存在或在中找不到主机名~/.hosts,该命令将正常执行。这应该与相关功能的原始标志一起使用,而与主机名相对于标志的放置位置无关,例如work ping -i 0.5 host1 -c 3。该~/.hosts文件优先于任何其他位置来查找主机名,因此,如果有任何重复的主机名,~/.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可以使用此“解析”吗?还是使用函数“ resolve”的函数?
秦丝

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
Pryftan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.