Tailscale, headsacle, headscale webui 配置(下)

上文介绍了用headscale、headscale webui 进行 Wireguard虚拟网络组网的配置方式。在实践中,通过tailscale网络在内网的Peer转发路由访问内部网络的其他主机时,仅靠访问内网的IP往往是不够的。很多服务要求使用域名访问,特别是内部域名,在外部也没有解析。这就需要进行DNS设置。

Tailscale网络的DNS设置

先来看Tailscale网络是如何处理DNS的:

官方已经说的很清楚了,文档在这里。

客户端(本机)发起Dns lookup,本地的tailscale客户端以100.100.100.100的名义返回DNS结果。其中,如果命中Tailnet的内建名称(Magic DNS, 由控制服务器push),返回内建名称对应的IP。

如果没有命中Tailnet的内建名称,则向Upstream DNS 提交查询(而不是向Headscale控制服务器查询!)

这个Upstream DNS是什么呢? 是客户端所在设备的本地DNS吗?

现在查看上篇中没有详解的,配置文件中关于DNS的内容:

dns_config:
  # Whether to prefer using Headscale provided DNS or use local.
  override_local_dns: true
  # List of DNS servers to expose to clients.
  nameservers:
    - 8.8.8.8
  # NextDNS (see https://tailscale.com/kb/1218/nextdns/).
  # "abc123" is example NextDNS ID, replace with yours.
  #
  # With metadata sharing:
  # nameservers:
  #   - https://dns.nextdns.io/abc123
  #
  # Without metadata sharing:
  # nameservers:
  #   - 2a07:a8c0::ab:c123
  #   - 2a07:a8c1::ab:c123
  # Split DNS (see https://tailscale.com/kb/1054/dns/),
  # list of search domains and the DNS to query for each one.
  #
  # restricted_nameservers:
  #   foo.bar.com:
  #     - 1.1.1.1
  #   darp.headscale.net:
  #     - 1.1.1.1
  #     - 8.8.8.8
  # Search domains to inject.
  domains: []
  # Extra DNS records
  # so far only A-records are supported (on the tailscale side)
  # See https://github.com/juanfont/headscale/blob/main/docs/dns-records.md#Limitations
  extra_records:
  #  - name: "test1.example.com",
  #     type: "A",
  #     value: "1.2.3.4"     
  #
  #   # you can also put it in one line
     - { name: "dns.example.com", type: "A", value: "1.2.3.4" }
     - { name: "dns2.example.com", type: "A", value: "5.6.7.8" }
  # Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
  # Only works if there is at least a nameserver defined.
  magic_dns: true
  # Defines the base domain to create the hostnames for MagicDNS.
  # `base_domain` must be a FQDNs, without the trailing dot.
  # The FQDN of the hosts will be
  # `hostname.user.base_domain` (e.g., _myhost.myuser.example.com_).
  base_domain: mydomain.com

可见,Headscale/Tailscale具有向客户端推送DNS服务器以及A记录(hosts)的功能。当然,在服务器打开override_local_dns 的同时,客户端也必须接受推送(–accept-dns=true)。

服务器支持向客户端推送的DNS方式有普通DNS,Nextdns(可以理解成是DOH,但是需要注册帐号),对限定的,Split DNS(指定FDQN向指定NS查询),以及直接返回hosts的指定A记录。

Tailnet Client Lookup on Local Network DNS

假设公司内网里有一个内部域名,指向一个内网地址,由一个该内网中的DNS服务器管理。

假设我们现在向客户端推送DNS设置为“普通DNS” 8.8.8.8,客户端在连接Tailnet后,即使可以通过在内网中的Tailnet 节点路由来连接内网的IP地址,也无法访问公司内部域名(如 service.mycompany.com)。

因为当Client查询service.mycompany.com时,Tailscale客户端将向被推送的”8.8.8.8“查询。如果客户端不接受推送的DNS服务,将使用客户端本地的DNS,同样不能得到目标内网中的内部DNS结果。

解决方法1,写入客户端的hosts(这办法很脏,手机也不行)

解决方法2,利用extra_records,在headscale控制服务器的配置文件中写入hosts,再下发给客户端。对于小型家庭网络,如果只需要较少的内部域名,这就足够了。

解决方法3,利用Split DNS,规定*.mycompany.com 全部由公司内网的DNS服务器解析。

问题:公司内网中的DNS服务器本身不在tailnet network中,其内网地址需要经过路由才能到达。在tailscale client的逻辑里,DNS查询如非指定,不会经过路由节点,因此指定的DNS服务器地址不可达。

可以在路由节点(或任何一个内网中以及加入Tailnet虚拟网络的,可以用虚拟网络地址直接访问的节点)上设置一个简单的dns缓存,如dnsmasq,由这个dnsmasq向内网中的DNS服务器请求。

通过Split DNS推送 100.64.0.1:53 处理 *.mycompany.com 的规则到客户端。客户端直接通过tailnet内部向路由节点上的dnsmasq查询。

通过路由节点转发内网DNS查询

Tailscale Client DNS behavior

下面研究一下,Tailscale/headscale 节点是否、什么时候需要接受控制服务器推送的DNS。

1,接受DNS推送(headscale推送的DNS配置以上文为准)–accept-dns=true

cat /etc/resolv.conf
resolv.conf(5) file generated by tailscale
For more info, see https://tailscale.com/s/resolvconf-overwrite
DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN

nameserver 100.100.100.100

search username.yourdomain.com

可见此时tailscale client 已经接管了主机的DNS服务器,服务器为100.100.100.100。

dig dns.example.com
#dig 一个不存在的域名,但在设置文件中有hosts A记录。

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.13 <<>> dns.example.com

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36030

;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0


;; QUESTION SECTION:

;dns.example.com. IN A


;; ANSWER SECTION:

dns.example.com. 600 IN A 1.2.3.4


;; Query time: 3 msec

;; SERVER: 100.100.100.100#53(100.100.100.100)

;; WHEN: Sun Apr 30 00:36:04 EDT 2023

;; MSG SIZE rcvd: 64

可见100.100.100.100 在3ms内就返回了结果 1.2.3.4,刚好是上文中配置文件中设置的hosts A记录。

2,关闭DNS推送 –accept-dns=false

dig www.youtube.com
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.13 <<>> www.youtube.com

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34301

;; flags: qr rd ra; QUERY: 1, ANSWER: 17, AUTHORITY: 0, ADDITIONAL: 1


;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 1232

;; QUESTION SECTION:

;www.youtube.com. IN A


;; ANSWER SECTION:

www.youtube.com. 86253 IN CNAME youtube-ui.l.google.com.

youtube-ui.l.google.com. 153 IN A 216.58.203.78

youtube-ui.l.google.com. 153 IN A 142.250.66.78

...


;; Query time: 10 msec

;; SERVER: 1.1.1.1#53(1.1.1.1)

;; WHEN: Sun Apr 30 00:40:02 EDT 2023

;; MSG SIZE rcvd: 334

服务器向1.1.1.1查询了www.youtube.com,不再使用headscale/tailscale推送的DNS结果。

再查询 dns.example.com 返回错误的结果,也说明不再接受内部的DNS结果。

何时应接受tailnet推送的DNS

作为客户端需要主动发起连接的情况下,可能需要推送的DNS(包含hosts)。如人使用的mac windows或是手机,需要主动访问某些自定义的dns。

作为出口/路由节点的主机,不需要推送的DNS,推送的DNS反而容易引发各种问题,比如增加了DNS的延迟。

发表回复

您的电子邮箱地址不会被公开。