summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorradhitya <alif@radhitya.org>2026-06-21 13:11:55 +0700
committerradhitya <alif@radhitya.org>2026-06-21 13:11:55 +0700
commit81661cc8deaacbff3497f0c9ef2625e98257ef76 (patch)
tree704e61822482cf5a9f18ef3b34cea2d4f78be4f3 /internal
parentb7359e1d45f505171356bcae3c7d5e2341ecc859 (diff)
dot, readme
Diffstat (limited to 'internal')
-rw-r--r--internal/config/config.go18
-rw-r--r--internal/server/server.go40
2 files changed, 51 insertions, 7 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index b2c88ee..42af236 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -15,14 +15,20 @@ type Config struct {
Admin AdminConfig `toml:"admin"`
ACL ACLConfig `toml:"acl"`
Log LogConfig `toml:"log"`
+ TLS TLSConfig `toml:"tls"`
}
type ServerConfig struct {
ListenUDP string `toml:"listen_udp"`
ListenTCP string `toml:"listen_tcp"`
ListenDOH string `toml:"listen_doh"`
+ ListenDoT string `toml:"listen_dot"`
}
+type TLSConfig struct {
+ Cert string `toml:"cert"`
+ Key string `toml:"key"`
+}
type CacheConfig struct {
MaxEntries int `toml:"max_entries"`
DBPath string `toml:"db_path"`
@@ -164,6 +170,15 @@ func Merge(dst, src Config) Config {
if src.Admin.Listen != "" {
dst.Admin.Listen = src.Admin.Listen
}
+ if src.Server.ListenDoT != "" {
+ dst.Server.ListenDoT = src.Server.ListenDoT
+ }
+ if src.TLS.Cert != "" {
+ dst.TLS.Cert = src.TLS.Cert
+ }
+ if src.TLS.Key != "" {
+ dst.TLS.Key = src.TLS.Key
+ }
return dst
}
@@ -202,5 +217,8 @@ func (c Config) Validate() error {
if c.Resolver.Mode == "forward" && len(c.Resolver.Forwarders) == 0 {
return fmt.Errorf("resolver mode=forward requires at least one forwarder")
}
+ if c.Server.ListenDoT != "" && (c.TLS.Cert == "" || c.TLS.Key == "") {
+ return fmt.Errorf("listen_dot requires tls.cert and tls.key")
+ }
return nil
}
diff --git a/internal/server/server.go b/internal/server/server.go
index a90e5ac..74add95 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -2,6 +2,7 @@ package server
import (
"context"
+ "crypto/tls"
"fmt"
"log/slog"
"net"
@@ -30,12 +31,13 @@ type Server struct {
admin *Admin
aclNets []*net.IPNet
rateLimiter *rateLimiter
+ dot *dns.Server
- mu sync.RWMutex
- upUDP bool
- upTCP bool
- upDoH bool
-
+ mu sync.RWMutex
+ upUDP bool
+ upTCP bool
+ upDoH bool
+ upDoT bool
cancel context.CancelFunc
}
@@ -45,10 +47,12 @@ func (s *Server) Ready() bool {
wantUDP := s.cfg.ListenUDP != ""
wantTCP := s.cfg.ListenTCP != ""
wantDoH := s.cfg.ListenDOH != ""
- return (!wantUDP || s.upUDP) && (!wantTCP || s.upTCP) && (!wantDoH || s.upDoH)
+ wantDoT := s.cfg.ListenDoT != ""
+ return (!wantUDP || s.upUDP) && (!wantTCP || s.upTCP) && (!wantDoH || s.upDoH) &&
+ (!wantDoT || s.upDoT)
}
-func New(udpAddr, tcpAddr, dohAddr string, logger *slog.Logger, r *resolver.Resolver, c *cache.Cache, bl *blocklist.Blocklist, cfg config.Config) (*Server, error) {
+func New(udpAddr, tcpAddr, dohAddr, dotAddr string, tlsCfg *tls.Config, logger *slog.Logger, r *resolver.Resolver, c *cache.Cache, bl *blocklist.Blocklist, cfg config.Config) (*Server, error) {
baseCtx, cancel := context.WithCancel(context.Background())
s := &Server{
logger: logger,
@@ -94,6 +98,16 @@ func New(udpAddr, tcpAddr, dohAddr string, logger *slog.Logger, r *resolver.Reso
}
}
+ if dotAddr != "" && tlsCfg != nil {
+
+ s.dot = &dns.Server{
+ Addr: dotAddr,
+ Net: "tcp",
+ Handler: mux,
+ TLSConfig: tlsCfg,
+ ReadTimeout: 5 * time.Second,
+ }
+ }
if dohAddr != "" {
dohMux := http.NewServeMux()
dohMux.HandleFunc("/dns-query", s.dohHandler)
@@ -122,6 +136,9 @@ func (s *Server) Run(ctx context.Context) error {
if s.doh != nil {
s.upDoH = true
}
+ if s.dot != nil {
+ s.upDoT = true
+ }
s.mu.Unlock()
if s.admin != nil {
@@ -149,6 +166,12 @@ func (s *Server) Run(ctx context.Context) error {
errCh <- s.doh.ListenAndServe()
}()
}
+ if s.dot != nil {
+ go func() {
+ s.logger.Info("dot listener active", "addr", s.dot.Addr)
+ errCh <- s.dot.ListenAndServe()
+ }()
+ }
select {
case <-ctx.Done():
@@ -180,6 +203,9 @@ func (s *Server) Close() error {
if s.tcp != nil {
s.tcp.Shutdown(context.Background())
}
+ if s.dot != nil {
+ s.dot.Shutdown(context.Background())
+ }
if s.doh != nil {
s.doh.Close()
}