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

red*_*ike 233 hosts not-root-user

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

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

小智 163

您正在寻找的功能是在 glibc 中实现的。您可以通过设置HOSTALIASES环境变量来定义自定义主机文件。此文件中的名称将由gethostbyname(请参阅文档)获取。

示例(在 Ubuntu 13.10 上测试):

$ echo 'g www.google.com' >> ~/.hosts
$ export HOSTALIASES=~/.hosts
$ wget g -O /dev/null
Run Code Online (Sandbox Code Playgroud)

一些限制:

  • HOSTALIASES仅适用于使用getaddrinfo(3)gethostbyname(3)
  • 对于setuid / setgid / setcap应用程序,libc 会清理环境,这意味着HOSTALIASES设置丢失。为setuid root或被赋予net_raw在执行能力(因为它需要监听ICMP数据包),所以HOSTALIASES不会与工作ping,除非你打电话之前已经是root ping

  • 请注意,如果您使用的是 `nscd` 并且仅限于没有点的主机名,则它不起作用。 (13认同)
  • 聚会迟到了,但这与所希望的相反,不是吗?我认为 OP 正在寻找一种类似的解决方案来向 /etc/hosts 添加主机解析条目,但可以在用户空间中完成而无需提升权限。(即`127.0.0.1 somedomain.com`) (6认同)
  • 这似乎不适用于 CentOS 6 (3认同)
  • `HOSTALIASES` 仅适用于**没有任何点**的名称 - 请参阅 [`__res_context_search()`](https://github.com/bminor/glibc/blob/4fc321dc58b2/resolv/res_query.c#L375-L380 ) (3认同)
  • 不适用于 MacOS :( (2认同)

Sté*_*las 47

除了LD_PRELOAD技巧。一个可能在一些系统上工作的简单替代方法是对处理主机名解析的系统库的副本进行二进制编辑,以替换/etc/hosts为您自己的路径。

例如,在 Linux 上:

如果您不使用nscd,请复制libnss_files.so到您自己的某个位置,例如:

mkdir -p -- ~/lib &&
cp /lib/x86_64-linux-gnu/libnss_files.so.2 ~/lib
Run Code Online (Sandbox Code Playgroud)

(共享库可能位于其他地方,例如/lib/libnss_files.so.2

现在,对副本进行二进制编辑以将其替换/etc/hosts为相同长度的内容,例如/tmp/hosts.

perl -pi -e 's:/etc/hosts:/tmp/hosts:g' ~/lib/libnss_files.so.2
Run Code Online (Sandbox Code Playgroud)

编辑/tmp/hosts以添加您想要的条目。并使用

export LD_LIBRARY_PATH=~/lib
Run Code Online (Sandbox Code Playgroud)

用于nss_files查看/tmp/hosts而不是/etc/hosts.

代替/tmp/hosts,您也可以制作它/dev/fd//3(此处使用两个斜杠,以便 的长度与 的长度/dev/fd//3相同/etc/hosts),然后执行

exec 3< ~/hosts
Run Code Online (Sandbox Code Playgroud)

例如,这将允许不同的命令使用不同的hosts文件。

如果nscd已安装并正在运行,您可以通过执行相同的技巧来绕过它,但这次libc.so.6将 nscd 套接字的路径(类似于/var/run/nscd/socket)替换为一些不存在的路径。

  • +1 大胆,-1 冲击值 (27认同)
  • @ParthianShot,您关于缺少更新的观点是有道理的。然而,对于你的另一点,如果一个流氓软件正在以你的名义运行,它对 $LD_LIBRARY_PATH 中的一个区域的写访问权限将是你最不担心的,因为它已经获得了对更糟糕和更可靠的区域的写访问,比如你的.bash*、crontab、.forward 以及您使用的所有软件的所有配置文件(例如,它可以设置 LD_{PRELOAD,LIBRARY_PATH} 但通常会做得更糟) (15认同)
  • +1 表示二进制补丁,-1 表示安全隐患 (10认同)
  • @ParthianShot,有什么安全隐患? (2认同)

fri*_*elp 31

使用该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
Run Code Online (Sandbox Code Playgroud)

  • 是的,它有效,您可以使用 --bind 将文件挂载到另一个文件上。 (7认同)
  • 等待。我认为 mount 只是将文件系统挂载到目录(挂载点)上。我不知道一个文件可以挂载到另一个文件上。这真的有效吗?(我是认真地问这个问题。这不是讽刺。) (3认同)
  • 正如对那些好奇的人的注释:这与名称空间有关;系统调用 *`unshare(2)`* 和 *`clone(2)`* 是这里魔法的一部分。另请参阅 *`namespaces(7)`* 和 *`user_namespaces(7)`*。 (2认同)

小智 7

一种解决方案是让每个用户在一个单独的chroot,因此它们可以各自具有单独的/etc/hosts自己。

  • 这可能是一个答案,但正如几乎没有解释的那样,它更适合作为评论 (3认同)
  • 嗯……是的,这是可行的。虽然 chrooting 是这种事情的一个非常重型的解决方案。并带来了它自己的一系列问题。 (2认同)

ban*_*die 7

我遇到了同样的需求,所以我尝试了 libnss-userhosts,但它在多线程应用程序中失败了。因此我写了libnss-homehosts。它非常新,仅由我测试过。你可以给它一个机会!它支持 /etc/host.conf 中的一些选项、多个别名和反向解析(地址到名称)。


Jas*_*son 3

不确定这是否对您有帮助,但我来这里寻找一种方法来添加保存的“主机”,只有我的用户才能轻松访问。

我基本上需要能够 ssh 进入我们工作网络上的某些盒子,该网络只有一个入口点。

我所做的是将别名添加到我的.bashrc文件中。

例如,如果您添加:

alias jrfbox='ssh jason@192.168.6.6' 
Run Code Online (Sandbox Code Playgroud)

~/.bashrc在你的(~是你的主目录)的底部。然后注销并再次登录后,您可以输入jrfbox,点击Enter,它将连接。

  • 如果您对 SSH 特别感兴趣,您应该查看“man ssh_config”。 (16认同)
  • 您不必注销并重新登录来重新加载 `~/.bashrc`,只需执行 `source ~/.bashrc` 即可。 (2认同)