787 lines
19 KiB
Go
787 lines
19 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"errors"
|
|||
|
|
"fmt"
|
|||
|
|
"net"
|
|||
|
|
"sync"
|
|||
|
|
"videoplayer/dao"
|
|||
|
|
"videoplayer/proto"
|
|||
|
|
|
|||
|
|
"github.com/miekg/dns"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// DNSServiceInstance 运行中的DNS服务实例
|
|||
|
|
type DNSServiceInstance struct {
|
|||
|
|
ServerID uint `json:"server_id"`
|
|||
|
|
Config *proto.DNSServer `json:"config"`
|
|||
|
|
Server *dns.Server `json:"-"`
|
|||
|
|
Running bool `json:"running"`
|
|||
|
|
mutex sync.Mutex `json:"-"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DNSServiceManager DNS服务管理器
|
|||
|
|
type DNSServiceManager struct {
|
|||
|
|
instances map[uint]*DNSServiceInstance
|
|||
|
|
rwMutex sync.RWMutex
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var dnsServiceManager *DNSServiceManager
|
|||
|
|
|
|||
|
|
func init() {
|
|||
|
|
dnsServiceManager = &DNSServiceManager{
|
|||
|
|
instances: make(map[uint]*DNSServiceInstance),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== DNSServer 相关操作 ====================
|
|||
|
|
|
|||
|
|
func CreateDNSServer(req *proto.CreateDNSServerReq, userID uint) (proto.DNSServer, error) {
|
|||
|
|
server := proto.DNSServer{
|
|||
|
|
UserID: userID,
|
|||
|
|
Name: req.Name,
|
|||
|
|
Port: req.Port,
|
|||
|
|
ListenIP: req.ListenIP,
|
|||
|
|
UpstreamDNS: req.UpstreamDNS,
|
|||
|
|
EnableRecursion: req.EnableRecursion,
|
|||
|
|
Status: proto.DNS_STATUS_STOPPED,
|
|||
|
|
Description: req.Description,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if server.Port == 0 {
|
|||
|
|
server.Port = 53
|
|||
|
|
}
|
|||
|
|
if server.ListenIP == "" {
|
|||
|
|
server.ListenIP = "0.0.0.0"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
id, err := dao.CreateDNSServer(server)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSServer{}, err
|
|||
|
|
}
|
|||
|
|
server.ID = id
|
|||
|
|
return server, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetDNSServerList(req *proto.GetDNSServerReq, userID uint) ([]proto.DNSServer, error) {
|
|||
|
|
var servers []proto.DNSServer
|
|||
|
|
var err error
|
|||
|
|
|
|||
|
|
if req.ServerID > 0 {
|
|||
|
|
server, err := dao.FindDNSServerByID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != userID && GetUserByIDFromUserCenter(int(userID)).Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
servers = append(servers, server)
|
|||
|
|
} else {
|
|||
|
|
if req.GetType == 0 {
|
|||
|
|
servers, err = dao.FindDNSServerByUserID(userID)
|
|||
|
|
} else if req.GetType == 1 {
|
|||
|
|
user := GetUserByIDFromUserCenter(int(userID))
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问,仅管理员可获取全部DNS服务器")
|
|||
|
|
}
|
|||
|
|
servers, err = dao.FindAllDNSServer()
|
|||
|
|
} else {
|
|||
|
|
return nil, errors.New("无效的获取类型")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return servers, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func UpdateDNSServer(req *proto.UpdateDNSServerReq, userID int) (proto.DNSServer, error) {
|
|||
|
|
server, err := dao.FindDNSServerByID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSServer{}, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return proto.DNSServer{}, errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
server.Name = req.Name
|
|||
|
|
server.Port = req.Port
|
|||
|
|
server.ListenIP = req.ListenIP
|
|||
|
|
server.UpstreamDNS = req.UpstreamDNS
|
|||
|
|
server.EnableRecursion = req.EnableRecursion
|
|||
|
|
server.Status = req.Status
|
|||
|
|
server.Description = req.Description
|
|||
|
|
|
|||
|
|
err = dao.UpdateDNSServer(server.ID, &server)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSServer{}, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果服务正在运行,自动重启以应用新配置
|
|||
|
|
go RestartDNSServerIfRunning(req.ServerID, userID)
|
|||
|
|
|
|||
|
|
return server, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func DeleteDNSServer(req *proto.DeleteDNSServerReq, userID int) error {
|
|||
|
|
user := GetUserByIDFromUserCenter(userID)
|
|||
|
|
if req.DelType == 0 && req.ServerID > 0 {
|
|||
|
|
server, err := dao.FindDNSServerByID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSZoneByServerID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSServerByID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
} else if req.DelType == 1 {
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问,仅管理员可删除所有DNS服务器")
|
|||
|
|
}
|
|||
|
|
servers, err := dao.FindAllDNSServer()
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
for _, server := range servers {
|
|||
|
|
err = dao.DeleteDNSZoneByServerID(server.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSServerByID(server.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return errors.New("无效的删除类型或参数")
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== DNSZone 相关操作 ====================
|
|||
|
|
|
|||
|
|
func CreateDNSZone(req *proto.CreateDNSZoneReq, userID uint) (proto.DNSZone, error) {
|
|||
|
|
server, err := dao.FindDNSServerByID(req.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSZone{}, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != userID && GetUserByIDFromUserCenter(int(userID)).Role != "admin" {
|
|||
|
|
return proto.DNSZone{}, errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
zone := proto.DNSZone{
|
|||
|
|
ServerID: req.ServerID,
|
|||
|
|
Domain: req.Domain,
|
|||
|
|
SOA_MName: req.SOA_MName,
|
|||
|
|
SOA_RName: req.SOA_RName,
|
|||
|
|
SOA_Serial: req.SOA_Serial,
|
|||
|
|
SOA_Refresh: req.SOA_Refresh,
|
|||
|
|
SOA_Retry: req.SOA_Retry,
|
|||
|
|
SOA_Expire: req.SOA_Expire,
|
|||
|
|
SOA_Minimum: req.SOA_Minimum,
|
|||
|
|
TTL: req.TTL,
|
|||
|
|
Description: req.Description,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if zone.SOA_Serial == 0 {
|
|||
|
|
zone.SOA_Serial = 1
|
|||
|
|
}
|
|||
|
|
if zone.SOA_Refresh == 0 {
|
|||
|
|
zone.SOA_Refresh = 86400
|
|||
|
|
}
|
|||
|
|
if zone.SOA_Retry == 0 {
|
|||
|
|
zone.SOA_Retry = 7200
|
|||
|
|
}
|
|||
|
|
if zone.SOA_Expire == 0 {
|
|||
|
|
zone.SOA_Expire = 3600000
|
|||
|
|
}
|
|||
|
|
if zone.SOA_Minimum == 0 {
|
|||
|
|
zone.SOA_Minimum = 3600
|
|||
|
|
}
|
|||
|
|
if zone.TTL == 0 {
|
|||
|
|
zone.TTL = 3600
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
id, err := dao.CreateDNSZone(zone)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSZone{}, err
|
|||
|
|
}
|
|||
|
|
zone.ID = id
|
|||
|
|
return zone, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetDNSZoneList(req *proto.GetDNSZoneReq, userID uint) ([]proto.DNSZone, error) {
|
|||
|
|
var zones []proto.DNSZone
|
|||
|
|
var err error
|
|||
|
|
|
|||
|
|
if req.ZoneID > 0 {
|
|||
|
|
zone, err := dao.FindDNSZoneByID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != userID && GetUserByIDFromUserCenter(int(userID)).Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问DNS区域")
|
|||
|
|
}
|
|||
|
|
zones = append(zones, zone)
|
|||
|
|
} else {
|
|||
|
|
if req.GetType == 0 {
|
|||
|
|
if req.ServerID > 0 {
|
|||
|
|
zones, err = dao.FindDNSZoneByServerID(req.ServerID)
|
|||
|
|
} else {
|
|||
|
|
servers, err := dao.FindDNSServerByUserID(userID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
for _, server := range servers {
|
|||
|
|
serverZones, err := dao.FindDNSZoneByServerID(server.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
zones = append(zones, serverZones...)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else if req.GetType == 1 {
|
|||
|
|
user := GetUserByIDFromUserCenter(int(userID))
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问,仅管理员可获取全部DNS区域")
|
|||
|
|
}
|
|||
|
|
if req.ServerID > 0 {
|
|||
|
|
zones, err = dao.FindDNSZoneByServerID(req.ServerID)
|
|||
|
|
} else {
|
|||
|
|
zones, err = dao.FindAllDNSZone()
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return nil, errors.New("无效的获取类型")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return zones, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func UpdateDNSZone(req *proto.UpdateDNSZoneReq, userID int) (proto.DNSZone, error) {
|
|||
|
|
zone, err := dao.FindDNSZoneByID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSZone{}, err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSZone{}, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return proto.DNSZone{}, errors.New("未授权访问DNS区域")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
zone.Domain = req.Domain
|
|||
|
|
zone.SOA_MName = req.SOA_MName
|
|||
|
|
zone.SOA_RName = req.SOA_RName
|
|||
|
|
zone.SOA_Serial = req.SOA_Serial
|
|||
|
|
zone.SOA_Refresh = req.SOA_Refresh
|
|||
|
|
zone.SOA_Retry = req.SOA_Retry
|
|||
|
|
zone.SOA_Expire = req.SOA_Expire
|
|||
|
|
zone.SOA_Minimum = req.SOA_Minimum
|
|||
|
|
zone.TTL = req.TTL
|
|||
|
|
zone.Description = req.Description
|
|||
|
|
|
|||
|
|
err = dao.UpdateDNSZone(zone.ID, &zone)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSZone{}, err
|
|||
|
|
}
|
|||
|
|
return zone, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func DeleteDNSZone(req *proto.DeleteDNSZoneReq, userID int) error {
|
|||
|
|
user := GetUserByIDFromUserCenter(userID)
|
|||
|
|
if req.DelType == 0 && req.ZoneID > 0 {
|
|||
|
|
zone, err := dao.FindDNSZoneByID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问DNS区域")
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSRecordByZoneID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSZoneByID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
} else if req.DelType == 1 {
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问,仅管理员可删除所有DNS区域")
|
|||
|
|
}
|
|||
|
|
zones, err := dao.FindAllDNSZone()
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
for _, zone := range zones {
|
|||
|
|
err = dao.DeleteDNSRecordByZoneID(zone.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSZoneByID(zone.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return errors.New("无效的删除类型或参数")
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== DNSRecord 相关操作 ====================
|
|||
|
|
|
|||
|
|
func CreateDNSRecord(req *proto.CreateDNSRecordReq, userID uint) (proto.DNSRecord, error) {
|
|||
|
|
zone, err := dao.FindDNSZoneByID(req.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != userID && GetUserByIDFromUserCenter(int(userID)).Role != "admin" {
|
|||
|
|
return proto.DNSRecord{}, errors.New("未授权访问DNS区域")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
record := proto.DNSRecord{
|
|||
|
|
ZoneID: req.ZoneID,
|
|||
|
|
Name: req.Name,
|
|||
|
|
Type: req.Type,
|
|||
|
|
Value: req.Value,
|
|||
|
|
TTL: req.TTL,
|
|||
|
|
Priority: req.Priority,
|
|||
|
|
Weight: req.Weight,
|
|||
|
|
Port: req.Port,
|
|||
|
|
Target: req.Target,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if record.TTL == 0 {
|
|||
|
|
record.TTL = zone.TTL
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
id, err := dao.CreateDNSRecord(record)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
record.ID = id
|
|||
|
|
return record, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetDNSRecordList(req *proto.GetDNSRecordReq, userID uint) ([]proto.DNSRecord, error) {
|
|||
|
|
var records []proto.DNSRecord
|
|||
|
|
var err error
|
|||
|
|
|
|||
|
|
if req.RecordID > 0 {
|
|||
|
|
record, err := dao.FindDNSRecordByID(req.RecordID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
zone, err := dao.FindDNSZoneByID(record.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != userID && GetUserByIDFromUserCenter(int(userID)).Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问DNS记录")
|
|||
|
|
}
|
|||
|
|
records = append(records, record)
|
|||
|
|
} else {
|
|||
|
|
if req.GetType == 0 {
|
|||
|
|
if req.ZoneID > 0 {
|
|||
|
|
records, err = dao.FindDNSRecordByZoneID(req.ZoneID)
|
|||
|
|
} else {
|
|||
|
|
servers, err := dao.FindDNSServerByUserID(userID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
for _, server := range servers {
|
|||
|
|
zones, err := dao.FindDNSZoneByServerID(server.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
for _, zone := range zones {
|
|||
|
|
zoneRecords, err := dao.FindDNSRecordByZoneID(zone.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
records = append(records, zoneRecords...)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else if req.GetType == 1 {
|
|||
|
|
user := GetUserByIDFromUserCenter(int(userID))
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问,仅管理员可获取全部DNS记录")
|
|||
|
|
}
|
|||
|
|
if req.ZoneID > 0 {
|
|||
|
|
records, err = dao.FindDNSRecordByZoneID(req.ZoneID)
|
|||
|
|
} else {
|
|||
|
|
records, err = dao.FindAllDNSRecord()
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return nil, errors.New("无效的获取类型")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return records, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func UpdateDNSRecord(req *proto.UpdateDNSRecordReq, userID int) (proto.DNSRecord, error) {
|
|||
|
|
record, err := dao.FindDNSRecordByID(req.RecordID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
zone, err := dao.FindDNSZoneByID(record.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return proto.DNSRecord{}, errors.New("未授权访问DNS记录")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
record.Name = req.Name
|
|||
|
|
record.Type = req.Type
|
|||
|
|
record.Value = req.Value
|
|||
|
|
record.TTL = req.TTL
|
|||
|
|
record.Priority = req.Priority
|
|||
|
|
record.Weight = req.Weight
|
|||
|
|
record.Port = req.Port
|
|||
|
|
record.Target = req.Target
|
|||
|
|
|
|||
|
|
err = dao.UpdateDNSRecord(record.ID, &record)
|
|||
|
|
if err != nil {
|
|||
|
|
return proto.DNSRecord{}, err
|
|||
|
|
}
|
|||
|
|
return record, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func DeleteDNSRecord(req *proto.DeleteDNSRecordReq, userID int) error {
|
|||
|
|
user := GetUserByIDFromUserCenter(userID)
|
|||
|
|
if req.DelType == 0 && req.RecordID > 0 {
|
|||
|
|
record, err := dao.FindDNSRecordByID(req.RecordID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
zone, err := dao.FindDNSZoneByID(record.ZoneID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
server, err := dao.FindDNSServerByID(zone.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问DNS记录")
|
|||
|
|
}
|
|||
|
|
err = dao.DeleteDNSRecordByID(req.RecordID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
} else if req.DelType == 1 {
|
|||
|
|
if user.Role != "admin" {
|
|||
|
|
return errors.New("未授权访问,仅管理员可删除所有DNS记录")
|
|||
|
|
}
|
|||
|
|
records, err := dao.FindAllDNSRecord()
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
for _, record := range records {
|
|||
|
|
err = dao.DeleteDNSRecordByID(record.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return errors.New("无效的删除类型或参数")
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== DNS 服务运行管理 ====================
|
|||
|
|
|
|||
|
|
// handleDNSRequest 处理DNS查询请求
|
|||
|
|
func (instance *DNSServiceInstance) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|||
|
|
m := new(dns.Msg)
|
|||
|
|
m.SetReply(r)
|
|||
|
|
m.Authoritative = true
|
|||
|
|
|
|||
|
|
for _, q := range r.Question {
|
|||
|
|
// 查找对应的Zone
|
|||
|
|
zones, err := dao.FindDNSZoneByServerID(instance.ServerID)
|
|||
|
|
if err != nil {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var matchedZone *proto.DNSZone
|
|||
|
|
var qName string = dns.Fqdn(q.Name)
|
|||
|
|
|
|||
|
|
for _, zone := range zones {
|
|||
|
|
zoneFqdn := dns.Fqdn(zone.Domain)
|
|||
|
|
if dns.IsSubDomain(zoneFqdn, qName) {
|
|||
|
|
matchedZone = &zone
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if matchedZone == nil {
|
|||
|
|
// 递归查询
|
|||
|
|
if instance.Config.EnableRecursion {
|
|||
|
|
c := new(dns.Client)
|
|||
|
|
upstreams := instance.Config.UpstreamDNS
|
|||
|
|
if upstreams == "" {
|
|||
|
|
upstreams = "8.8.8.8:53"
|
|||
|
|
}
|
|||
|
|
resp, _, err := c.Exchange(r, upstreams)
|
|||
|
|
if err == nil {
|
|||
|
|
m.Answer = append(m.Answer, resp.Answer...)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查找匹配的记录
|
|||
|
|
records, err := dao.FindDNSRecordByZoneID(matchedZone.ID)
|
|||
|
|
if err != nil {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, record := range records {
|
|||
|
|
recordName := dns.Fqdn(record.Name + "." + matchedZone.Domain)
|
|||
|
|
if record.Name == "@" {
|
|||
|
|
recordName = dns.Fqdn(matchedZone.Domain)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if recordName == qName && record.Type == uint(q.Qtype) {
|
|||
|
|
var rr dns.RR
|
|||
|
|
var ttl uint32
|
|||
|
|
if record.TTL > 0 {
|
|||
|
|
ttl = uint32(record.TTL)
|
|||
|
|
} else {
|
|||
|
|
ttl = uint32(matchedZone.TTL)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch q.Qtype {
|
|||
|
|
case dns.TypeA:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN A %s", q.Name, ttl, record.Value))
|
|||
|
|
case dns.TypeAAAA:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN AAAA %s", q.Name, ttl, record.Value))
|
|||
|
|
case dns.TypeCNAME:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN CNAME %s", q.Name, ttl, record.Value))
|
|||
|
|
case dns.TypeMX:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN MX %d %s", q.Name, ttl, record.Priority, record.Value))
|
|||
|
|
case dns.TypeNS:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN NS %s", q.Name, ttl, record.Value))
|
|||
|
|
case dns.TypeTXT:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN TXT \"%s\"", q.Name, ttl, record.Value))
|
|||
|
|
case dns.TypeSRV:
|
|||
|
|
rr, _ = dns.NewRR(fmt.Sprintf("%s %d IN SRV %d %d %d %s", q.Name, ttl, record.Priority, record.Weight, record.Port, record.Target))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if rr != nil {
|
|||
|
|
m.Answer = append(m.Answer, rr)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
w.WriteMsg(m)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// StartDNSServer 启动DNS服务
|
|||
|
|
func StartDNSServer(serverID uint, userID int) (*DNSServiceInstance, error) {
|
|||
|
|
// 检查权限
|
|||
|
|
server, err := dao.FindDNSServerByID(serverID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dnsServiceManager.rwMutex.Lock()
|
|||
|
|
defer dnsServiceManager.rwMutex.Unlock()
|
|||
|
|
|
|||
|
|
// 检查是否已经在运行
|
|||
|
|
if instance, exists := dnsServiceManager.instances[serverID]; exists && instance.Running {
|
|||
|
|
return instance, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建服务实例
|
|||
|
|
instance := &DNSServiceInstance{
|
|||
|
|
ServerID: serverID,
|
|||
|
|
Config: &server,
|
|||
|
|
Running: false,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建DNS服务器
|
|||
|
|
dns.HandleFunc(".", instance.handleDNSRequest)
|
|||
|
|
|
|||
|
|
addr := fmt.Sprintf("%s:%d", server.ListenIP, server.Port)
|
|||
|
|
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
udpConn, err := net.ListenUDP("udp", udpAddr)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
|||
|
|
if err != nil {
|
|||
|
|
udpConn.Close()
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tcpListener, err := net.ListenTCP("tcp", tcpAddr)
|
|||
|
|
if err != nil {
|
|||
|
|
udpConn.Close()
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
instance.Server = &dns.Server{
|
|||
|
|
Listener: tcpListener,
|
|||
|
|
PacketConn: udpConn,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 启动服务
|
|||
|
|
go func() {
|
|||
|
|
instance.mutex.Lock()
|
|||
|
|
instance.Running = true
|
|||
|
|
instance.mutex.Unlock()
|
|||
|
|
|
|||
|
|
err := instance.Server.ActivateAndServe()
|
|||
|
|
if err != nil {
|
|||
|
|
instance.mutex.Lock()
|
|||
|
|
instance.Running = false
|
|||
|
|
instance.mutex.Unlock()
|
|||
|
|
}
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
// 更新数据库状态
|
|||
|
|
server.Status = proto.DNS_STATUS_RUNNING
|
|||
|
|
dao.UpdateDNSServer(serverID, &server)
|
|||
|
|
|
|||
|
|
dnsServiceManager.instances[serverID] = instance
|
|||
|
|
return instance, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// StopDNSServer 停止DNS服务
|
|||
|
|
func StopDNSServer(serverID uint, userID int) error {
|
|||
|
|
server, err := dao.FindDNSServerByID(serverID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dnsServiceManager.rwMutex.Lock()
|
|||
|
|
defer dnsServiceManager.rwMutex.Unlock()
|
|||
|
|
|
|||
|
|
instance, exists := dnsServiceManager.instances[serverID]
|
|||
|
|
if !exists || !instance.Running {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 停止服务
|
|||
|
|
err = instance.Server.Shutdown()
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
instance.mutex.Lock()
|
|||
|
|
instance.Running = false
|
|||
|
|
instance.mutex.Unlock()
|
|||
|
|
|
|||
|
|
// 更新数据库状态
|
|||
|
|
server.Status = proto.DNS_STATUS_STOPPED
|
|||
|
|
dao.UpdateDNSServer(serverID, &server)
|
|||
|
|
|
|||
|
|
delete(dnsServiceManager.instances, serverID)
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RestartDNSServer 重启DNS服务
|
|||
|
|
func RestartDNSServer(serverID uint, userID int) (*DNSServiceInstance, error) {
|
|||
|
|
err := StopDNSServer(serverID, userID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return StartDNSServer(serverID, userID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetDNSServerStatus 获取DNS服务运行状态
|
|||
|
|
func GetDNSServerStatus(serverID uint, userID int) (*DNSServiceInstance, error) {
|
|||
|
|
server, err := dao.FindDNSServerByID(serverID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if server.UserID != uint(userID) && GetUserByIDFromUserCenter(userID).Role != "admin" {
|
|||
|
|
return nil, errors.New("未授权访问DNS服务器")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dnsServiceManager.rwMutex.RLock()
|
|||
|
|
defer dnsServiceManager.rwMutex.RUnlock()
|
|||
|
|
|
|||
|
|
instance, exists := dnsServiceManager.instances[serverID]
|
|||
|
|
if exists {
|
|||
|
|
return instance, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 不在运行中,返回配置中的状态
|
|||
|
|
return &DNSServiceInstance{
|
|||
|
|
ServerID: serverID,
|
|||
|
|
Config: &server,
|
|||
|
|
Running: server.Status == proto.DNS_STATUS_RUNNING,
|
|||
|
|
}, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RestartDNSServerIfRunning 如果服务正在运行则重启(配置更新时调用)
|
|||
|
|
func RestartDNSServerIfRunning(serverID uint, userID int) error {
|
|||
|
|
dnsServiceManager.rwMutex.RLock()
|
|||
|
|
instance, exists := dnsServiceManager.instances[serverID]
|
|||
|
|
dnsServiceManager.rwMutex.RUnlock()
|
|||
|
|
|
|||
|
|
if exists && instance.Running {
|
|||
|
|
// 获取最新配置
|
|||
|
|
server, err := dao.FindDNSServerByID(serverID)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
// 重启服务(管理员权限)
|
|||
|
|
_, err = RestartDNSServer(server.ID, userID) // 假设管理员ID为1
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|