实现DNS域名验证

This commit is contained in:
刘祥超
2022-09-10 16:13:21 +08:00
parent 9699a9adad
commit e95b0bd9a6
7 changed files with 190 additions and 243 deletions

View File

@@ -4,31 +4,35 @@ import "github.com/iwind/TeaGo/dbs"
// NSDomain DNS域名 // NSDomain DNS域名
type NSDomain struct { type NSDomain struct {
Id uint64 `field:"id"` // ID Id uint64 `field:"id"` // ID
ClusterId uint32 `field:"clusterId"` // 集群ID ClusterId uint32 `field:"clusterId"` // 集群ID
UserId uint32 `field:"userId"` // 用户ID UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用 IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 域名 Name string `field:"name"` // 域名
GroupIds dbs.JSON `field:"groupIds"` // 分组ID GroupIds dbs.JSON `field:"groupIds"` // 分组ID
Tsig dbs.JSON `field:"tsig"` // TSIG配置 Tsig dbs.JSON `field:"tsig"` // TSIG配置
CreatedAt uint64 `field:"createdAt"` // 创建时间 VerifyTXT string `field:"verifyTXT"` // 验证用的TXT
Version uint64 `field:"version"` // 版本号 VerifyExpiresAt uint64 `field:"verifyExpiresAt"` // 验证TXT过期时间
Status string `field:"status"` // 状态none|verified CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态 Version uint64 `field:"version"` // 版本号
Status string `field:"status"` // 状态none|verified
State uint8 `field:"state"` // 状态
} }
type NSDomainOperator struct { type NSDomainOperator struct {
Id interface{} // ID Id any // ID
ClusterId interface{} // 集群ID ClusterId any // 集群ID
UserId interface{} // 用户ID UserId any // 用户ID
IsOn interface{} // 是否启用 IsOn any // 是否启用
Name interface{} // 域名 Name any // 域名
GroupIds interface{} // 分组ID GroupIds any // 分组ID
Tsig interface{} // TSIG配置 Tsig any // TSIG配置
CreatedAt interface{} // 创建时间 VerifyTXT any // 验证用的TXT
Version interface{} // 版本号 VerifyExpiresAt any // 验证TXT过期时间
Status interface{} // 状态none|verified CreatedAt any // 创建时间
State interface{} // 状态 Version any // 版本号
Status any // 状态none|verified
State any // 状态
} }
func NewNSDomainOperator() *NSDomainOperator { func NewNSDomainOperator() *NSDomainOperator {

View File

@@ -1,11 +1,7 @@
package models package models
import ( import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
@@ -82,68 +78,6 @@ func (this *NSClusterDAO) FindEnabledNSClusterName(tx *dbs.Tx, id int64) (string
FindStringCol("") FindStringCol("")
} }
// CreateCluster 创建集群
func (this *NSClusterDAO) CreateCluster(tx *dbs.Tx, name string, accessLogRefJSON []byte) (int64, error) {
var op = NewNSClusterOperator()
op.Name = name
if len(accessLogRefJSON) > 0 {
op.AccessLog = accessLogRefJSON
}
op.IsOn = true
op.State = NSClusterStateEnabled
// 默认端口
// TCP
{
var config = &serverconfigs.TCPProtocolConfig{}
config.IsOn = true
config.Listen = []*serverconfigs.NetworkAddressConfig{
{
Protocol: serverconfigs.ProtocolTCP,
PortRange: "53",
},
}
configJSON, err := json.Marshal(config)
if err != nil {
return 0, err
}
op.Tcp = configJSON
}
// UDP
{
var config = &serverconfigs.UDPProtocolConfig{}
config.IsOn = true
config.Listen = []*serverconfigs.NetworkAddressConfig{
{
Protocol: serverconfigs.ProtocolUDP,
PortRange: "53",
},
}
configJSON, err := json.Marshal(config)
if err != nil {
return 0, err
}
op.Udp = configJSON
}
return this.SaveInt64(tx, op)
}
// UpdateCluster 修改集群
func (this *NSClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, isOn bool) error {
if clusterId <= 0 {
return errors.New("invalid clusterId")
}
var op = NewNSClusterOperator()
op.Id = clusterId
op.Name = name
op.IsOn = isOn
return this.Save(tx, op)
}
// CountAllEnabledClusters 计算可用集群数量 // CountAllEnabledClusters 计算可用集群数量
func (this *NSClusterDAO) CountAllEnabledClusters(tx *dbs.Tx) (int64, error) { func (this *NSClusterDAO) CountAllEnabledClusters(tx *dbs.Tx) (int64, error) {
return this.Query(tx). return this.Query(tx).
@@ -189,23 +123,6 @@ func (this *NSClusterDAO) FindAllEnabledClusterIds(tx *dbs.Tx) ([]int64, error)
return result, nil return result, nil
} }
// UpdateClusterAccessLog 设置访问日志
func (this *NSClusterDAO) UpdateClusterAccessLog(tx *dbs.Tx, clusterId int64, accessLogJSON []byte) error {
return this.Query(tx).
Pk(clusterId).
Set("accessLog", accessLogJSON).
UpdateQuickly()
}
// FindClusterAccessLog 读取访问日志配置
func (this *NSClusterDAO) FindClusterAccessLog(tx *dbs.Tx, clusterId int64) ([]byte, error) {
accessLog, err := this.Query(tx).
Pk(clusterId).
Result("accessLog").
FindStringCol("")
return []byte(accessLog), err
}
// FindClusterGrantId 查找集群的认证ID // FindClusterGrantId 查找集群的认证ID
func (this *NSClusterDAO) FindClusterGrantId(tx *dbs.Tx, clusterId int64) (int64, error) { func (this *NSClusterDAO) FindClusterGrantId(tx *dbs.Tx, clusterId int64) (int64, error) {
return this.Query(tx). return this.Query(tx).
@@ -214,102 +131,6 @@ func (this *NSClusterDAO) FindClusterGrantId(tx *dbs.Tx, clusterId int64) (int64
FindInt64Col(0) FindInt64Col(0)
} }
// UpdateRecursion 设置递归DNS
func (this *NSClusterDAO) UpdateRecursion(tx *dbs.Tx, clusterId int64, recursionJSON []byte) error {
err := this.Query(tx).
Pk(clusterId).
Set("recursion", recursionJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, clusterId)
}
// FindClusterRecursion 读取递归DNS配置
func (this *NSClusterDAO) FindClusterRecursion(tx *dbs.Tx, clusterId int64) ([]byte, error) {
recursion, err := this.Query(tx).
Result("recursion").
Pk(clusterId).
FindStringCol("")
if err != nil {
return nil, err
}
return []byte(recursion), nil
}
// FindClusterTCP 查找集群的TCP设置
func (this *NSClusterDAO) FindClusterTCP(tx *dbs.Tx, clusterId int64) ([]byte, error) {
return this.Query(tx).
Pk(clusterId).
Result("tcp").
FindBytesCol()
}
// UpdateClusterTCP 修改集群的TCP设置
func (this *NSClusterDAO) UpdateClusterTCP(tx *dbs.Tx, clusterId int64, tcpConfig *serverconfigs.TCPProtocolConfig) error {
tcpJSON, err := json.Marshal(tcpConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(clusterId).
Set("tcp", tcpJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, clusterId)
}
// FindClusterTLS 查找集群的TLS设置
func (this *NSClusterDAO) FindClusterTLS(tx *dbs.Tx, clusterId int64) ([]byte, error) {
return this.Query(tx).
Pk(clusterId).
Result("tls").
FindBytesCol()
}
// UpdateClusterTLS 修改集群的TLS设置
func (this *NSClusterDAO) UpdateClusterTLS(tx *dbs.Tx, clusterId int64, tlsConfig *serverconfigs.TLSProtocolConfig) error {
tlsJSON, err := json.Marshal(tlsConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(clusterId).
Set("tls", tlsJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, clusterId)
}
// FindClusterUDP 查找集群的TCP设置
func (this *NSClusterDAO) FindClusterUDP(tx *dbs.Tx, clusterId int64) ([]byte, error) {
return this.Query(tx).
Pk(clusterId).
Result("udp").
FindBytesCol()
}
// UpdateClusterUDP 修改集群的UDP设置
func (this *NSClusterDAO) UpdateClusterUDP(tx *dbs.Tx, clusterId int64, udpConfig *serverconfigs.UDPProtocolConfig) error {
udpJSON, err := json.Marshal(udpConfig)
if err != nil {
return err
}
err = this.Query(tx).
Pk(clusterId).
Set("udp", udpJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyUpdate(tx, clusterId)
}
// CountAllClustersWithSSLPolicyIds 计算使用SSL策略的所有NS集群数量 // CountAllClustersWithSSLPolicyIds 计算使用SSL策略的所有NS集群数量
func (this *NSClusterDAO) CountAllClustersWithSSLPolicyIds(tx *dbs.Tx, sslPolicyIds []int64) (count int64, err error) { func (this *NSClusterDAO) CountAllClustersWithSSLPolicyIds(tx *dbs.Tx, sslPolicyIds []int64) (count int64, err error) {
if len(sslPolicyIds) == 0 { if len(sslPolicyIds) == 0 {
@@ -326,45 +147,6 @@ func (this *NSClusterDAO) CountAllClustersWithSSLPolicyIds(tx *dbs.Tx, sslPolicy
Count() Count()
} }
// FindClusterDDoSProtection 获取集群的DDoS设置
func (this *NSClusterDAO) FindClusterDDoSProtection(tx *dbs.Tx, clusterId int64) (*ddosconfigs.ProtectionConfig, error) {
one, err := this.Query(tx).
Result("ddosProtection").
Pk(clusterId).
Find()
if one == nil || err != nil {
return nil, err
}
return one.(*NSCluster).DecodeDDoSProtection(), nil
}
// UpdateClusterDDoSProtection 设置集群的DDoS设置
func (this *NSClusterDAO) UpdateClusterDDoSProtection(tx *dbs.Tx, clusterId int64, ddosProtection *ddosconfigs.ProtectionConfig) error {
if clusterId <= 0 {
return ErrNotFound
}
var op = NewNSClusterOperator()
op.Id = clusterId
if ddosProtection == nil {
op.DdosProtection = "{}"
} else {
ddosProtectionJSON, err := json.Marshal(ddosProtection)
if err != nil {
return err
}
op.DdosProtection = ddosProtectionJSON
}
err := this.Save(tx, op)
if err != nil {
return err
}
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, NSNodeTaskTypeDDosProtectionChanged)
}
// NotifyUpdate 通知更改 // NotifyUpdate 通知更改
func (this *NSClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error { func (this *NSClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, NSNodeTaskTypeConfigChanged) return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, NSNodeTaskTypeConfigChanged)

View File

@@ -16,6 +16,7 @@ type NSCluster struct {
Tls dbs.JSON `field:"tls"` // TLS设置 Tls dbs.JSON `field:"tls"` // TLS设置
Udp dbs.JSON `field:"udp"` // UDP设置 Udp dbs.JSON `field:"udp"` // UDP设置
DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置 DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置
Hosts dbs.JSON `field:"hosts"` // DNS主机地址
} }
type NSClusterOperator struct { type NSClusterOperator struct {
@@ -31,6 +32,7 @@ type NSClusterOperator struct {
Tls any // TLS设置 Tls any // TLS设置
Udp any // UDP设置 Udp any // UDP设置
DdosProtection any // DDoS防护设置 DdosProtection any // DDoS防护设置
Hosts any // DNS主机地址
} }
func NewNSClusterOperator() *NSClusterOperator { func NewNSClusterOperator() *NSClusterOperator {

View File

@@ -2,6 +2,7 @@ package models
import ( import (
"encoding/json" "encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
) )
@@ -14,7 +15,7 @@ func (this *NSCluster) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
var result = &ddosconfigs.ProtectionConfig{} var result = &ddosconfigs.ProtectionConfig{}
err := json.Unmarshal(this.DdosProtection, &result) err := json.Unmarshal(this.DdosProtection, &result)
if err != nil { if err != nil {
// ignore err remotelogs.Error("NSCluster.DecodeDDoSProtection", "decode failed: "+err.Error())
} }
return result return result
} }
@@ -26,4 +27,19 @@ func (this *NSCluster) HasDDoSProtection() bool {
return config.IsOn() return config.IsOn()
} }
return false return false
} }
// DecodeHosts 解析主机地址
func (this *NSCluster) DecodeHosts() []string {
if IsNull(this.Hosts) {
return nil
}
var hosts = []string{}
err := json.Unmarshal(this.Hosts, &hosts)
if err != nil {
remotelogs.Error("NSCluster.DecodeHosts", "decode failed: "+err.Error())
}
return hosts
}

File diff suppressed because one or more lines are too long

123
internal/utils/lookup.go Normal file
View File

@@ -0,0 +1,123 @@
package utils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/miekg/dns"
)
// LookupCNAME 查询CNAME记录
// TODO 可以设置使用的DNS主机地址
func LookupCNAME(host string) (string, error) {
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
return "", err
}
var c = new(dns.Client)
var m = new(dns.Msg)
m.SetQuestion(host+".", dns.TypeCNAME)
m.RecursionDesired = true
var lastErr error
for _, serverAddr := range config.Servers {
r, _, err := c.Exchange(m, configutils.QuoteIP(serverAddr)+":"+config.Port)
if err != nil {
lastErr = err
continue
}
if len(r.Answer) == 0 {
continue
}
return r.Answer[0].(*dns.CNAME).Target, nil
}
return "", lastErr
}
// LookupNS 查询NS记录
// TODO 可以设置使用的DNS主机地址
func LookupNS(host string) ([]string, error) {
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
return nil, err
}
var c = new(dns.Client)
var m = new(dns.Msg)
m.SetQuestion(host+".", dns.TypeNS)
m.RecursionDesired = true
var result = []string{}
var lastErr error
var hasValidServer = false
for _, serverAddr := range config.Servers {
r, _, err := c.Exchange(m, configutils.QuoteIP(serverAddr)+":"+config.Port)
if err != nil {
lastErr = err
continue
}
hasValidServer = true
if len(r.Answer) == 0 {
continue
}
for _, answer := range r.Answer {
result = append(result, answer.(*dns.NS).Ns)
}
break
}
if hasValidServer {
return result, nil
}
return nil, lastErr
}
// LookupTXT 获取CNAME
// TODO 可以设置使用的DNS主机地址
func LookupTXT(host string) ([]string, error) {
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
return nil, err
}
var c = new(dns.Client)
var m = new(dns.Msg)
m.SetQuestion(host + ".", dns.TypeTXT)
m.RecursionDesired = true
var lastErr error
var result = []string{}
var hasValidServer = false
for _, serverAddr := range config.Servers {
r, _, err := c.Exchange(m, configutils.QuoteIP(serverAddr)+":"+config.Port)
if err != nil {
lastErr = err
continue
}
hasValidServer = true
if len(r.Answer) == 0 {
continue
}
for _, answer := range r.Answer {
result = append(result, answer.(*dns.TXT).Txt...)
}
break
}
if hasValidServer {
return result, nil
}
return nil, lastErr
}

View File

@@ -0,0 +1,20 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package utils_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"testing"
)
func TestLookupCNAME(t *testing.T) {
t.Log(utils.LookupCNAME("www.yun4s.cn"))
}
func TestLookupNS(t *testing.T) {
t.Log(utils.LookupNS("goedge.cn"))
}
func TestLookupTXT(t *testing.T) {
t.Log(utils.LookupTXT("yanzheng.goedge.cn"))
}