v1.5.1 增强程序稳定性

This commit is contained in:
robin
2026-03-22 17:37:40 +08:00
parent afbaaa869c
commit 17e182b413
652 changed files with 22949 additions and 34397 deletions

View File

@@ -2,6 +2,7 @@ package nodes
import (
"errors"
"fmt"
"log"
"net"
"os"
@@ -46,7 +47,14 @@ func (n *HTTPDNSNode) Run() {
return
}
go n.start()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]goroutine panic: %v", r))
}
}()
n.start()
}()
select {}
}
@@ -108,6 +116,12 @@ func (n *HTTPDNSNode) listenSock() error {
}
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]sock goroutine panic: %v", r))
}
}()
n.sock.OnCommand(func(cmd *gosock.Command) {
switch cmd.Code {
case "pid":
@@ -152,12 +166,47 @@ func (n *HTTPDNSNode) start() {
taskManager := NewTaskManager(n.quitCh, snapshotManager)
resolveServer := NewResolveServer(n.quitCh, snapshotManager)
go snapshotManager.Start()
go statusManager.Start()
go taskManager.Start()
go resolveServer.Start()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]snapshot goroutine panic: %v", r))
}
}()
snapshotManager.Start()
}()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]status goroutine panic: %v", r))
}
}()
statusManager.Start()
}()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]task goroutine panic: %v", r))
}
}()
taskManager.Start()
}()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]resolve goroutine panic: %v", r))
}
}()
resolveServer.Start()
}()
go NewUpgradeManager().Loop()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE]upgrade goroutine panic: %v", r))
}
}()
NewUpgradeManager().Loop()
}()
}
func (n *HTTPDNSNode) stop() {

View File

@@ -166,7 +166,14 @@ func NewResolveServer(quitCh <-chan struct{}, snapshotManager *SnapshotManager)
}
func (s *ResolveServer) Start() {
go s.startAccessLogFlusher()
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE][resolve]access log flusher panic: %v", r))
}
}()
s.startAccessLogFlusher()
}()
// 1. Load initial certificate from file (fallback)
if len(s.certFile) > 0 && len(s.keyFile) > 0 {
@@ -323,6 +330,12 @@ func (s *ResolveServer) startListener(addr string) error {
}
go func() {
defer func() {
if r := recover(); r != nil {
log.Println(fmt.Sprintf("[HTTPDNS_NODE][resolve]serve goroutine panic: %v", r))
}
}()
if err := srv.Serve(tlsLn); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Println("[HTTPDNS_NODE][resolve]serve failed on", addr, ":", err.Error())
}
@@ -498,11 +511,18 @@ func (s *ResolveServer) handleResolve(writer http.ResponseWriter, request *http.
clientIP := detectClientIP(request, query.Get("cip"))
clientProfile := buildClientRouteProfile(clientIP)
// ECS 只使用可信来源的 IPcip 参数或直连 RemoteAddr
// 不信任 X-Forwarded-For 等可被客户端伪造的转发头
ecsIP := normalizeIPCandidate(query.Get("cip"))
if len(ecsIP) == 0 {
ecsIP = normalizeIPCandidate(request.RemoteAddr)
}
clusterTTL := pickDefaultTTL(snapshot, loadedApp.App)
rule, records, ttl := pickRuleRecords(loadedDomain.Rules, qtype, clientProfile, clusterTTL)
if len(records) == 0 {
// Fallback回源上游 DNS 查询真实记录
fallbackRecords, fallbackTTL, fallbackErr := fallbackResolve(domain, qtype)
fallbackRecords, fallbackTTL, fallbackErr := fallbackResolve(domain, qtype, ecsIP, isMainlandChinaCountry(clientProfile.Country))
if fallbackErr != nil || len(fallbackRecords) == 0 {
errMsg := "未找到解析记录"
if fallbackErr != nil {
@@ -929,8 +949,49 @@ func pickRuleRecords(rules []*pb.HTTPDNSCustomRule, qtype string, profile *clien
return bestRule, bestRecords, bestTTL
}
// addECSOption 向 DNS 请求中设置 EDNS Client Subnet (ECS)。
// 如果请求已携带 ECS 则覆盖(避免双 ECS 导致上游 malformed request
func addECSOption(m *dns.Msg, clientIP string) {
if len(clientIP) == 0 {
return
}
ip := net.ParseIP(clientIP)
if ip == nil {
return
}
ecs := &dns.EDNS0_SUBNET{
Code: dns.EDNS0SUBNET,
}
if ip.To4() != nil {
ecs.Family = 1 // IPv4
ecs.SourceNetmask = 24
ecs.Address = ip.To4()
} else {
ecs.Family = 2 // IPv6
ecs.SourceNetmask = 56
ecs.Address = ip
}
opt := m.IsEdns0()
if opt == nil {
m.SetEdns0(4096, false)
opt = m.IsEdns0()
}
if opt != nil {
// 删除已有的 ECS option避免出现双 EDNS0_SUBNET
var filtered []dns.EDNS0
for _, o := range opt.Option {
if o.Option() != dns.EDNS0SUBNET {
filtered = append(filtered, o)
}
}
opt.Option = append(filtered, ecs)
}
}
// fallbackResolve 当无自定义规则命中时,回源上游 DNS 查询真实记录(对齐 EdgeDNS 做法)
func fallbackResolve(domain string, qtype string) ([]*resolveRecord, int32, error) {
func fallbackResolve(domain string, qtype string, clientIP string, isChina bool) ([]*resolveRecord, int32, error) {
var dnsType uint16
switch qtype {
case "A":
@@ -945,16 +1006,18 @@ func fallbackResolve(domain string, qtype string) ([]*resolveRecord, int32, erro
m.SetQuestion(dns.Fqdn(domain), dnsType)
m.RecursionDesired = true
// 优先使用本机 /etc/resolv.conf 中的 DNS 服务器(对齐 EdgeDNS
var upstream = "223.5.5.5:53"
resolveConfig, confErr := dns.ClientConfigFromFile("/etc/resolv.conf")
if confErr == nil && len(resolveConfig.Servers) > 0 {
port := resolveConfig.Port
if len(port) == 0 {
port = "53"
}
server := resolveConfig.Servers[rands.Int(0, len(resolveConfig.Servers)-1)]
upstream = server + ":" + port
// 携带客户端真实 IPECS向上游查询确保 GeoIP 结果准确
addECSOption(m, clientIP)
// 根据客户端 IP 地理位置选择上游 DNS
// 中国大陆客户端 → 阿里 DNS出口在中国ECS + 出口双重匹配)
// 海外客户端 → Google DNS出口在海外
// 这样递归 DNS 出口和 ECS 子网指向同一区域CDN 调度更准确
var upstream string
if isChina {
upstream = "223.5.5.5:53"
} else {
upstream = "8.8.8.8:53"
}
r, _, err := sharedRecursionDNSClient.Exchange(m, upstream)

View File

@@ -91,6 +91,12 @@ func (this *UpgradeManager) Start() {
log.Println("[UPGRADE_MANAGER]upgrade successfully")
go func() {
defer func() {
if r := recover(); r != nil {
log.Println("[UPGRADE_MANAGER]goroutine panic:", r)
}
}()
err = this.restart()
if err != nil {
log.Println("[UPGRADE_MANAGER]" + err.Error())