# Deploy Reverse DNS server

> A guide to deploying a Reverse DNS server using the SND project for ARIN-allocated IP addresses, enabling automatic PTR record generation for both IPv4 and IPv6 ranges.

Author: Vincent Yang
Published: 2024-10-07
Tags: Reverse DNS, DNS
Source: https://missuo.me/posts/reverse-dns-server

---

> 大多数情况下我们只会接触 DNS 服务器，也就是正向 DNS 服务器。它的全称是 Domain Name System，主要用于将域名转换为 IP 地址。然而 Reverse DNS 服务器顾名思义，是用于将 IP 地址转换为域名。

## 为什么要部署 Reverse DNS 服务器

我似乎没有找到公开的 Reverse DNS 服务器，因此唯一的方式就是自己部署一个。在 [ARIN](https://www.arin.net) 分配 IP 之后，我需要拥有 Reverse DNS 服务器才可以正常地显示 IP 的 Hostname 信息。

## 部署

用到的项目是 [https://github.com/Jamesits/SND](https://github.com/Jamesits/SND)，这个名字也很有意思，是把 DNS 反过来！步骤也非常容易，仅需配置一份 `config.toml` 文件，然后运行即可。


以下是作者提供的一份实例文件，提供了多种样式的域名生成方式。
```toml
# This is an example config of SND.

listen = [
    # protocol:ip.addr:port
    "tcp::53",
    "udp::53",
]

# set to the domain names of your authoritive DNS servers
NS = [
    "ns1.example.com.",
    "ns2.example.com.",
]

# use DNS pointer compression
compress_dns_messages = true

# disable querying DNS server version by a DNS request
allow_version_reporting = false
# alternatively, you can fake the version string
# version_string = "bind-⑨"

# This will become the default SOA record for all your networks, unless overrided.
# Make it exactly the same across all servers.
[SOA]
# your primary NS, usually the domain name of one of your NS servers, dot at end
MName = "ns1.example.com."
# your email in dot notation, dot at end
RName = "dnsmaster.example.com."
## Optional fields, see Wikipedia for explanation
# Serial = 1970010101
# Refresh = 86400
# Retry = 7200
# Expire = 3600000
# TTL = 172800

# Define your nets here
[[net]]
net = "192.168.1.0/24"
mode = "prefix_ltr"
domain = "example.com"
# Generates "192.168.1.1.example.com."

[[net]]
net = "192.168.2.0/24"
mode = "prefix_rtl"
domain = "example.com"
# Generates "1.2.168.192.example.com."

[[net]]
net = "192.168.3.0/24"
mode = "fixed"
domain = "example.com"
# Generates "example.com."

[[net]]
net = "192.168.4.0/24"
mode = "prefix_ltr"
domain = "example.com"
domain_prefix = "yes."
# Generates "yes.192.168.4.1.example.com."
# Note: domain_prefix is applied without any sanity check. Make sure it doesn't violate the rules.

[[net]]
net = "fd00::/48"
mode = "prefix_ltr"
domain = "example.com"
# Works for IPv6 too! Generates "f.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.example.com."

[[net]]
net = "fd00:1::/48"
mode = "prefix_ltr"
domain = "example.com"
ipv6_notation = "four_hexs"
# Default IPv6 notation is too long for you? This generates "fd00.1.0.0.0.0.0.1.example.com."

[host]
# quick way to generate a static record for a static IP
"10.10.10.10" = "internal10.example.com"
"10.10.10.20" = "internal20.example.com"
```

我最终选择采用的配置如下：

```toml
# Define your nets here
[[net]]
net = "23.191.8.0/24"
mode = "prefix_ltr"
domain = "owo.network"
# Generates "23.191.8.1.owo.network."

[[net]]
net = "2602:f7ee::/40"
mode = "prefix_ltr"
domain = "owo.network"
ipv6_notation = "four_hexs"
# Generates "2602.f7ee.0.0.0.0.0.1.owo.network."
```

## 效果

```
~ dig -x 23.191.8.8

; <<>> DiG 9.10.6 <<>> -x 23.191.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57608
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;8.8.191.23.in-addr.arpa.	IN	PTR

;; ANSWER SECTION:
8.8.191.23.in-addr.arpa. 114510	IN	PTR	23.191.8.8.owo.network.

;; Query time: 1 msec
;; SERVER: 10.0.0.1#53(10.0.0.1)
;; WHEN: Mon Oct 07 19:41:26 EDT 2024
;; MSG SIZE  rcvd: 88
```

![20241005lfvgsn](https://i.uid.si/img/20241005lfvgsn.png)