如何让 DNS 解析在 El Capitan 上的 Mac OS X `chroot` 中工作?
How can I get DNS resolution to work inside a Mac OS X `chroot` on El Capitan?
我正在尝试为 运行 一个需要互联网访问权限的程序创建一个 chroot,以便为我自己构建一个沙盒化的、不可变的开发人员环境。到目前为止,我的监狱运行良好:我可以在里面 运行 bash 并从那里 运行 简单的程序!但是 DNS 解析不起作用:
bash-3.2$ curl google.ca
curl: (6) Could not resolve host: google.ca
我几乎肯定这是因为内部进程无法连接到监狱外的 mDNSResponder
守护程序 运行ning。在监狱外面有一个 mDNSResponder
套接字供整个系统使用:
host ➜ ls -lA /var/run/mDNSResponder
srw-rw-rw- 1 root daemon 0 22 Oct 10:41 /var/run/mDNSResponder
但是,监狱里面没有。因此,我尝试使用 socat
从监狱内部到监狱外部创建一个 unix 套接字 "proxy":我 运行 socat
(下面的命令)在我的内部创建一个套接字jail,然后在 jail 运行 里面再次卷曲,但 curl 仍然给出相同的错误信息。在使用 SIGUSR1:
打开 mDNSResponder
的详细日志记录后,我在系统日志中看到了这一点
2015-10-26 5:32:30.835 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:30.835 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23271](socat)
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23271](socat)
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:31.339 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:31.339 PM curl[23269]: dnssd_clientstub write_all(4) failed -1/28 32 Broken pipe
2015-10-26 5:32:31.341 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:31.341 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23272](socat)
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23272](socat)
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:31.844 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:31.846 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:31.846 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23274](socat)
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23274](socat)
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:32.349 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:32.350 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:32.351 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23275](socat)
2015-10-26 5:32:33.361 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23275](socat)
2015-10-26 5:32:33.361 PM mDNSResponder[95]: 12: Removing FD
在我看来像 curl
通过 dnssd_clientstub
正在尝试三次解析名称。这是被监禁进程尝试连接时的 socat
日志:
host ~/C/jail (master*) ➜
sudo socat -v -d -d UNIX-LISTEN:/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder,mode=666,fork,user=root,group=daemon UNIX-CLIENT:/private/var/run/mDNSResponder
Password:
2015/10/26 18:16:03 socat[24334] N listening on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24334] N accepting connection from LEN=16 AF=1 "" on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24334] N forked off child process 24341
2015/10/26 18:16:07 socat[24334] N listening on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24341] N opening connection to LEN=32 AF=1 "/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24341] N successfully connected from local address LEN=16 AF=1 ""
2015/10/26 18:16:07 socat[24341] N starting data transfer loop with FDs [6,6] and [5,5]
> 2015/10/26 18:16:07.081847 length=28 from=0 to=27
............................< 2015/10/26 18:16:07.082019 length=4 from=0 to=3
....> 2015/10/26 18:16:07.082167 length=50 from=28 to=77
...............\b...............P.....google.ca....> 2015/10/26 18:16:07.082287 length=1 from=78 to=78
.2015/10/26 18:16:07 socat[24341] N socket 2 (fd 5) is at EOF
2015/10/26 18:16:07 socat[24341] N exiting with status 0
2015/10/26 18:16:07 socat[24334] N childdied(): handling signal 20
为了比较,这是我从主机 运行 成功查找时的样子:
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 501
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23190](curl)
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: Result code socket 27 created 00000000 00000001
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(15000, 0, google.ca., Addr) START PID[23190]()
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: Result code socket 27 closed 00000000 00000001 (0)
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.251
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.249
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.227
*snip*
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: Result code socket 27 created 00000000 00000002
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(15000, 0, google.ca., AAAA) START PID[23190]()
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Result code socket 27 closed 00000000 00000002 (0)
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., AAAA) ADD 16 google.ca. AAAA 2607:F8B0:400B:080A:0000:0000:0000:100F
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Cancel 00000000 00000001
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) STOP PID[23190]()
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Cancel 00000000 00000002
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., AAAA) STOP PID[23190]()
2015-10-26 5:31:56.587 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23190](curl)
2015-10-26 5:31:56.587 PM mDNSResponder[95]: 12: Removing FD
我注意到失败和成功之间的主要区别是 uid
对于监狱内的请求为 0,对于监狱外的请求为 501。很好奇,但这似乎并不是请求实际失败的地方。
来自 mDNSResponder
的错误消息似乎与通过套接字从传入请求中获取 errsd
有关。 https://github.com/jevinskie/mDNSResponder/blob/2942dde61f920fbbf96ff9a3840567ebbe7cb1b6/mDNSShared/uds_daemon.c#L3660
此时在我看来 mDNSResponder
希望它的客户通过套接字向它传递一对 fd 以响应客户,我不确定甚至可以从内部做到这一点chroot。我是一个非常糟糕的 C 程序员,所以我对此可能是错的,但如果这是真的,是否有可能这样做,是否有更好的途径让 DNS 在 chroot 中工作?
其他花絮:
您可以配置 mDNSResponder
以在其启动的 plist 文件中侦听多个套接字,但该文件现在受系统完整性保护保护,我不想禁用它让这个工作。它很笨拙,而且很容易与我经常在主机上更改的监狱文件系统不同步,如果它因为文件不存在而无法创建套接字之一,则会破坏每个进程的 DNS。 运行 代理似乎更有弹性
ping
在监狱中瞬间死亡,这就是我使用curl
的原因。它立即在控制台上收到 Killed: 9
消息。
我正在使用绑定挂载将一些其他文件放入 chroot,但我无法让它在 mDNSResponder
套接字上工作。我使用 http://bindfs.org(因为 OS X 不支持 Linux' mount --bind
)在 /var/run 中挂载到 chroot,但这出现在日志中尝试连接时:
2015-10-26 6:39:40.833 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 1
2015-10-26 6:39:41.837 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 2
2015-10-26 6:39:42.843 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 3
2015-10-26 6:39:43.848 PM curl[25002]: dnssd_clientstub ConnectToServer: connect() failed path:/var/run/mDNSResponder Socket:4 Err:-1 Errno:61 Connection refused
您应该确保在您的 chroot 中有一个 /etc/resolv.conf
的副本。没有它,它就不知道要联系哪些 DNS 服务器,因此唯一的后备选项是使用 mDNS。但即使 mDNS 可以工作,它也可能只能用它解析本地域名,而不是 google.ca
.
这里的问题是 /var/run/mDNSResponder
套接字上的请求和响应使用 recvmsg
和 sendmsg
系统调用的 "ancillary data" 特性,而 socat 没有代理辅助数据。我能够获得一个自定义代理,它确实中继辅助数据以工作并为 chroot 内的进程提供 DNS。
顺便说一句,here is 一个重复的问题。另一个问题的最后答案对我有用。基本上创建一个 hard link 从“var/run/mDNSResponder”到“$CHROOT_PATH/var/run/mDNSResponder”..确保“/etc/resolv.conf" 出现在 chroot 环境中,并且在 chroot 中可以正常工作。
无需创建自定义套接字转发器。
我正在尝试为 运行 一个需要互联网访问权限的程序创建一个 chroot,以便为我自己构建一个沙盒化的、不可变的开发人员环境。到目前为止,我的监狱运行良好:我可以在里面 运行 bash 并从那里 运行 简单的程序!但是 DNS 解析不起作用:
bash-3.2$ curl google.ca
curl: (6) Could not resolve host: google.ca
我几乎肯定这是因为内部进程无法连接到监狱外的 mDNSResponder
守护程序 运行ning。在监狱外面有一个 mDNSResponder
套接字供整个系统使用:
host ➜ ls -lA /var/run/mDNSResponder
srw-rw-rw- 1 root daemon 0 22 Oct 10:41 /var/run/mDNSResponder
但是,监狱里面没有。因此,我尝试使用 socat
从监狱内部到监狱外部创建一个 unix 套接字 "proxy":我 运行 socat
(下面的命令)在我的内部创建一个套接字jail,然后在 jail 运行 里面再次卷曲,但 curl 仍然给出相同的错误信息。在使用 SIGUSR1:
mDNSResponder
的详细日志记录后,我在系统日志中看到了这一点
2015-10-26 5:32:30.835 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:30.835 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23271](socat)
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23271](socat)
2015-10-26 5:32:30.836 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:31.339 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:31.339 PM curl[23269]: dnssd_clientstub write_all(4) failed -1/28 32 Broken pipe
2015-10-26 5:32:31.341 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:31.341 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23272](socat)
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23272](socat)
2015-10-26 5:32:31.342 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:31.844 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:31.846 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:31.846 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23274](socat)
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: read_msg: ERROR failed to get errsd via SCM_RIGHTS
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23274](socat)
2015-10-26 5:32:31.847 PM mDNSResponder[95]: 12: Removing FD
2015-10-26 5:32:32.349 PM curl[23269]: dnssd_clientstub read_all(5) failed 0/4 0
2015-10-26 5:32:32.350 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 0
2015-10-26 5:32:32.351 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23275](socat)
2015-10-26 5:32:33.361 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23275](socat)
2015-10-26 5:32:33.361 PM mDNSResponder[95]: 12: Removing FD
在我看来像 curl
通过 dnssd_clientstub
正在尝试三次解析名称。这是被监禁进程尝试连接时的 socat
日志:
host ~/C/jail (master*) ➜
sudo socat -v -d -d UNIX-LISTEN:/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder,mode=666,fork,user=root,group=daemon UNIX-CLIENT:/private/var/run/mDNSResponder
Password:
2015/10/26 18:16:03 socat[24334] N listening on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24334] N accepting connection from LEN=16 AF=1 "" on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24334] N forked off child process 24341
2015/10/26 18:16:07 socat[24334] N listening on LEN=67 AF=1 "/Users/hornairs/Code/jail/jail-test/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24341] N opening connection to LEN=32 AF=1 "/private/var/run/mDNSResponder"
2015/10/26 18:16:07 socat[24341] N successfully connected from local address LEN=16 AF=1 ""
2015/10/26 18:16:07 socat[24341] N starting data transfer loop with FDs [6,6] and [5,5]
> 2015/10/26 18:16:07.081847 length=28 from=0 to=27
............................< 2015/10/26 18:16:07.082019 length=4 from=0 to=3
....> 2015/10/26 18:16:07.082167 length=50 from=28 to=77
...............\b...............P.....google.ca....> 2015/10/26 18:16:07.082287 length=1 from=78 to=78
.2015/10/26 18:16:07 socat[24341] N socket 2 (fd 5) is at EOF
2015/10/26 18:16:07 socat[24341] N exiting with status 0
2015/10/26 18:16:07 socat[24334] N childdied(): handling signal 20
为了比较,这是我从主机 运行 成功查找时的样子:
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: connect_callback: Adding FD for uid 501
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: DNSServiceCreateConnection START PID[23190](curl)
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: Result code socket 27 created 00000000 00000001
2015-10-26 5:31:56.524 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(15000, 0, google.ca., Addr) START PID[23190]()
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: Result code socket 27 closed 00000000 00000001 (0)
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.251
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.249
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) ADD 4 google.ca. Addr 74.216.233.227
*snip*
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: Result code socket 27 created 00000000 00000002
2015-10-26 5:31:56.525 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(15000, 0, google.ca., AAAA) START PID[23190]()
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Result code socket 27 closed 00000000 00000002 (0)
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., AAAA) ADD 16 google.ca. AAAA 2607:F8B0:400B:080A:0000:0000:0000:100F
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Cancel 00000000 00000001
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., Addr) STOP PID[23190]()
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: Cancel 00000000 00000002
2015-10-26 5:31:56.526 PM mDNSResponder[95]: 12: DNSServiceQueryRecord(google.ca., AAAA) STOP PID[23190]()
2015-10-26 5:31:56.587 PM mDNSResponder[95]: 12: DNSServiceCreateConnection STOP PID[23190](curl)
2015-10-26 5:31:56.587 PM mDNSResponder[95]: 12: Removing FD
我注意到失败和成功之间的主要区别是 uid
对于监狱内的请求为 0,对于监狱外的请求为 501。很好奇,但这似乎并不是请求实际失败的地方。
来自 mDNSResponder
的错误消息似乎与通过套接字从传入请求中获取 errsd
有关。 https://github.com/jevinskie/mDNSResponder/blob/2942dde61f920fbbf96ff9a3840567ebbe7cb1b6/mDNSShared/uds_daemon.c#L3660
此时在我看来 mDNSResponder
希望它的客户通过套接字向它传递一对 fd 以响应客户,我不确定甚至可以从内部做到这一点chroot。我是一个非常糟糕的 C 程序员,所以我对此可能是错的,但如果这是真的,是否有可能这样做,是否有更好的途径让 DNS 在 chroot 中工作?
其他花絮:
您可以配置
mDNSResponder
以在其启动的 plist 文件中侦听多个套接字,但该文件现在受系统完整性保护保护,我不想禁用它让这个工作。它很笨拙,而且很容易与我经常在主机上更改的监狱文件系统不同步,如果它因为文件不存在而无法创建套接字之一,则会破坏每个进程的 DNS。 运行 代理似乎更有弹性ping
在监狱中瞬间死亡,这就是我使用curl
的原因。它立即在控制台上收到Killed: 9
消息。我正在使用绑定挂载将一些其他文件放入 chroot,但我无法让它在
mDNSResponder
套接字上工作。我使用 http://bindfs.org(因为 OS X 不支持 Linux'mount --bind
)在 /var/run 中挂载到 chroot,但这出现在日志中尝试连接时:2015-10-26 6:39:40.833 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 1 2015-10-26 6:39:41.837 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 2 2015-10-26 6:39:42.843 PM curl[25002]: dnssd_clientstub ConnectToServer: connect()-> No of tries: 3 2015-10-26 6:39:43.848 PM curl[25002]: dnssd_clientstub ConnectToServer: connect() failed path:/var/run/mDNSResponder Socket:4 Err:-1 Errno:61 Connection refused
您应该确保在您的 chroot 中有一个 /etc/resolv.conf
的副本。没有它,它就不知道要联系哪些 DNS 服务器,因此唯一的后备选项是使用 mDNS。但即使 mDNS 可以工作,它也可能只能用它解析本地域名,而不是 google.ca
.
这里的问题是 /var/run/mDNSResponder
套接字上的请求和响应使用 recvmsg
和 sendmsg
系统调用的 "ancillary data" 特性,而 socat 没有代理辅助数据。我能够获得一个自定义代理,它确实中继辅助数据以工作并为 chroot 内的进程提供 DNS。
顺便说一句,here is 一个重复的问题。另一个问题的最后答案对我有用。基本上创建一个 hard link 从“var/run/mDNSResponder”到“$CHROOT_PATH/var/run/mDNSResponder”..确保“/etc/resolv.conf" 出现在 chroot 环境中,并且在 chroot 中可以正常工作。 无需创建自定义套接字转发器。