Answers:
您要寻找的功能已在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)
HOSTALIASES
设置会丢失。ping是setuid root(因为它需要侦听ICMP数据包),因此HOSTALIASES
,除非您在调用ping之前已经是root用户,否则ping无法使用。nscd
,并且仅限于没有点的主机名。
127.0.0.1 somedomain.com
)
getcap /usr/sbin/ping
,可能会看到类似:的信息/usr/bin/ping = cap_net_admin,cap_net_raw+p
。从技术上讲,它需要打开一个原始套接字而不是ICMP(但我想您可以说这只是语义)。
除了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
)。
LD_LIBRARY_PATH
为指向用户拥有的目录意味着用户运行的任何其他进程可以使用该目录来选择通过替换库产生的任何新进程。和更新libnss_files.so
通过包管理器(包括安全更新)将不会反映在修补版本。LD_LIBRARY_PATH
出于其他原因,建议修改通常是一件坏事,但由于这些问题,这也是不明智的。
使用该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
unshare(2)
,clone(2)
这是这里魔术的一部分。另请参阅namespaces(7)
和user_namespaces(7)
。
一种解决方案是将每个用户都放在一个单独的chroot
,这样他们每个人都/etc/hosts
可以自己拥有一个单独的。
我遇到了同样的需求,所以我尝试了libnss-userhosts,但是在多线程应用程序上失败了。因此,我写了libnss-homehosts。这是很新的,只有我自己测试过。您可以为此机会!它支持/etc/host.conf中的某些选项,多个别名和反向解析(地址到名称)。
将以下内容~/.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
不知道这是否对您有帮助,但是我来到这里寻找一种在只有我的用户可以轻松访问的地方添加保存的“主机”的方法。
我基本上需要能够放入我们工作网络中的某些框,该框只有一个入口点。
我所做的就是在.bashrc
文件中添加别名。
例如,如果您添加了:
alias jrfbox='ssh jason@192.168.6.6'
~/.bashrc
(~
位于您的主目录的底部)。然后注销并再次登录后,您可以输入jrfbox
,点击Enter,它将连接。
man ssh_config
。
~/.bashrc
,只需执行即可source ~/.bashrc
。
. ~/.bashrc