我想在 example.com 上的自托管服务器上维护 DNS 隧道。我还有一个 DNS 服务器,它为 example.com 提供一切服务。我目前正在使用dns2tcp对于 DNS 隧道,在域 tunnel.example.com 上。 NSD3用于服务权威区域,因为它既简单又安全。
但是,我只有一个公共 IPv4 地址,这意味着 NSD 和 dns2tcp 无法在同一个 IP/端口上监听。
所以我目前正在使用PowerDNS 递归器使用forward-zones
如下参数:
forward-zones-recurse=tunnel.example.com=1.2.3.4:5354
forward-zones=example.com=1.2.3.4:5353
这样可以将对权威区域的请求以及隧道请求发送到正确的服务器。NSD 正在监听端口 5353,而 dns2tcp 正在监听端口 5354。
然而,这很糟糕,因为递归器需要打开。它实际上回答了任何递归查询。
您对此有什么解决方案吗?我真的更喜欢不涉及设置 BIND 的解决方案,但如果您想说服我,请不要犹豫 ;)
编辑:我更改标题使其更清晰。
答案1
两台服务器不能同时监听同一个 IP+端口组合。
为了启用这种双后端猛兽,你需要做的就是黑客- 这是错误与不善不应该这么做。痛苦、悲伤、疯狂和死亡都存在于这条路上——现在就回头,否则你会被恶魔吃掉。
正确的解决方案
获取另一个 IP。最好是获取另一台服务器,并且不要在与权威 DNS 相同的机器上运行递归 DNS。
简单的解决方案
克服对 BIND 的恐惧/不信任/仇恨(获取一份DNS 和 BIND并使其变得美好),并使用allow-recursion{…};
指令来限制谁可以进行递归查询。
这种简单的解决方案可能仍会让您面临缓存中毒和其他恶意行为的风险。如果您真的希望权威 DNS 服务器安全,则需要运行一个单独的名称服务器进程来监听单独的 IP 地址,最好是在单独的主机(或监狱、虚拟机等)上。
答案2
2021 年更新
string
来自的模块的解决方案iptables
(见下文)无法翻译nftables
,所以我不得不寻找另一种解决方案。
我现在正在使用域名系统这是一个 DNS 负载平衡器。它使用更多的 CPU 和 RAM,但显然功能更强大。我喜欢它专注于这项任务,除非有请求,否则不会重写 DNS 答案。以下是我的配置文件摘录:
-- dnsdist configuration file, an example can be found in /usr/share/doc/dnsdist/examples/
-- disable security status polling via DNS
setSecurityPollSuffix("")
setLocal('<PUBLIC_IP4>:53', {reusePort=true, interface="eth_adsl"})
addLocal('[<PUBLIC_IP6>]:53', {reusePort=true, interface="eth_adsl"})
setACL({'0.0.0.0/0', '::/0'})
controlSocket('127.0.0.1')
setKey("SECRET_KEY")
-- Declare NSD authoritative server. It could also listen to localhost, but I let it answer on public addresses, using port 5300
newServer({address="[<PUBLIC_IP6>]:5300", checkInterval=60, pool="root"})
newServer({address="<PUBLIC_IP4>:5300", checkInterval=60, pool="root"})
-- Declare DNS Tunnel (iodine), on port 5354
newServer({address="127.0.0.1:5354", pool="tunnel"})
-- This is using socket activation, so disable dnsdist checks to avoid waking up the tunnel
getServer(2):setUp()
-- Forward to tunnel, skipping cache
tunnelRule = makeRule("t.antipoul.fr")
addAction(tunnelRule, SkipCacheAction())
addAction(tunnelRule, PoolAction("tunnel"))
-- Allow Zone transfer from secondary only
-- See https://dnsdist.org/advanced/axfr.html
addAction(AndRule({OrRule({QTypeRule(DNSQType.AXFR), QTypeRule(DNSQType.IXFR)}), NotRule(makeRule("<SECONDARY_IP4>/32"))}), RCodeAction(DNSRCode.REFUSED))
-- All remaining traffic goes to NSD
addAction(AllRule(), PoolAction("root"))
2012 年原始解决方案
我找到了一个解决方案。但是,它不是该问题的通用解决方案。
在我的例子中,我依赖 dns2tcp 使用的协议,该协议使用 tunnel.example.com 上的子域请求进行通信。因此,想法是匹配包含此类请求的数据包,并构建一个 netfilter 规则:
iptables -t nat -I PREROUTING -p udp --dport 53 -m string --algo bm --from 42 --hex-string "|0674756e6e656c076578616d706c6503636f6d00|" -j REDIRECT -to-ports 5354
- 参数是DNS数据包中所见的
hex-string
对应的字符串 。tunnel.example.com
- 确保
from 42
只有子请求被重定向到 dns2tcp,而不是域本身的常规请求(例如 SOA 或 NS 请求)。 - NSD 现在监听端口 53,比以前好多了。
- 不再有公共递归服务器,这更好。
这并不完美,但它确实比以前使用的软件少得多。