mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-06 14:50:25 +08:00
自建DNS支持递归查询
This commit is contained in:
@@ -129,6 +129,8 @@ func (this *NodesAction) RunGet(params struct {
|
|||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
"canAccess": addr.CanAccess,
|
"canAccess": addr.CanAccess,
|
||||||
|
"isUp": addr.IsUp,
|
||||||
|
"isOn": addr.IsOn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ func (this *IndexAction) searchNodes(keyword string) {
|
|||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
"canAccess": addr.CanAccess,
|
"canAccess": addr.CanAccess,
|
||||||
|
"isOn": addr.IsOn,
|
||||||
|
"isUp": addr.IsUp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
"canAccess": addr.CanAccess,
|
"canAccess": addr.CanAccess,
|
||||||
|
"isOn": addr.IsOn,
|
||||||
|
"isUp": addr.IsUp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
"canAccess": addr.CanAccess,
|
"canAccess": addr.CanAccess,
|
||||||
|
"isOn": addr.IsOn,
|
||||||
|
"isUp": addr.IsUp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
"name": addr.Name,
|
"name": addr.Name,
|
||||||
"ip": addr.Ip,
|
"ip": addr.Ip,
|
||||||
"canAccess": addr.CanAccess,
|
"canAccess": addr.CanAccess,
|
||||||
|
"isOn": addr.IsOn,
|
||||||
|
"isUp": addr.IsUp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
package cluster
|
package accessLog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package cluster
|
package accessLog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package recursion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "setting", "")
|
||||||
|
this.SecondMenu("recursion")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
this.Data["clusterId"] = params.ClusterId
|
||||||
|
|
||||||
|
resp, err := this.RPC().NSClusterRPC().FindNSClusterRecursionConfig(this.AdminContext(), &pb.FindNSClusterRecursionConfigRequest{NsClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = &dnsconfigs.RecursionConfig{}
|
||||||
|
if len(resp.RecursionJSON) > 0 {
|
||||||
|
err = json.Unmarshal(resp.RecursionJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.UseLocalHosts = true
|
||||||
|
}
|
||||||
|
this.Data["config"] = config
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
RecursionJSON []byte
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改DNS集群 %d 的递归DNS设置", params.ClusterId)
|
||||||
|
|
||||||
|
// TODO 校验域名
|
||||||
|
|
||||||
|
_, err := this.RPC().NSClusterRPC().UpdateNSClusterRecursionConfig(this.AdminContext(), &pb.UpdateNSClusterRecursionConfigRequest{
|
||||||
|
NsClusterId: params.ClusterId,
|
||||||
|
RecursionJSON: params.RecursionJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package recursion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||||
|
Helper(new(clusterutils.ClusterHelper)).
|
||||||
|
Data("teaMenu", "ns").
|
||||||
|
Data("teaSubMenu", "cluster").
|
||||||
|
Prefix("/ns/clusters/cluster/settings/recursion").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -78,15 +78,21 @@ func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext
|
|||||||
// 设置菜单
|
// 设置菜单
|
||||||
func (this *ClusterHelper) createSettingMenu(cluster *pb.NSCluster, selectedItem string) (items []maps.Map) {
|
func (this *ClusterHelper) createSettingMenu(cluster *pb.NSCluster, selectedItem string) (items []maps.Map) {
|
||||||
clusterId := numberutils.FormatInt64(cluster.Id)
|
clusterId := numberutils.FormatInt64(cluster.Id)
|
||||||
items = append(items, maps.Map{
|
return []maps.Map{
|
||||||
|
{
|
||||||
"name": "基础设置",
|
"name": "基础设置",
|
||||||
"url": "/ns/clusters/cluster/settings?clusterId=" + clusterId,
|
"url": "/ns/clusters/cluster/settings?clusterId=" + clusterId,
|
||||||
"isActive": selectedItem == "basic",
|
"isActive": selectedItem == "basic",
|
||||||
})
|
},
|
||||||
items = append(items, maps.Map{
|
{
|
||||||
"name": "访问日志",
|
"name": "访问日志",
|
||||||
"url": "/ns/clusters/cluster/settings/accessLog?clusterId=" + clusterId,
|
"url": "/ns/clusters/cluster/settings/accessLog?clusterId=" + clusterId,
|
||||||
"isActive": selectedItem == "accessLog",
|
"isActive": selectedItem == "accessLog",
|
||||||
})
|
},
|
||||||
return
|
{
|
||||||
|
"name": "递归DNS",
|
||||||
|
"url": "/ns/clusters/cluster/settings/recursion?clusterId=" + clusterId,
|
||||||
|
"isActive": selectedItem == "recursion",
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import (
|
|||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/settings"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/settings"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/settings/accessLog"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/settings/accessLog"
|
||||||
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/settings/recursion"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/logs"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/logs"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/routes"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/routes"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings/accesslogs"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings/accesslogs"
|
||||||
|
|||||||
@@ -32,12 +32,13 @@ Vue.component("ns-access-log-box", {
|
|||||||
this.$refs.box.parentNode.style.cssText = ""
|
this.$refs.box.parentNode.style.cssText = ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div class="access-log-row" :style="{'color': (accessLog.nsRecordId == null || accessLog.nsRecordId == 0) ? '#dc143c' : ''}" ref="box">
|
template: `<div class="access-log-row" :style="{'color': (!accessLog.isRecursive && (accessLog.nsRecordId == null || accessLog.nsRecordId == 0) || (accessLog.isRecursive && accessLog.recordValue != null && accessLog.recordValue.length == 0)) ? '#dc143c' : ''}" ref="box">
|
||||||
<span v-if="accessLog.region != null && accessLog.region.length > 0" class="grey">[{{accessLog.region}}]</span> <keyword :v-word="vKeyword">{{accessLog.remoteAddr}}</keyword> [{{accessLog.timeLocal}}] [{{accessLog.networking}}] <em>{{accessLog.questionType}} <keyword :v-word="vKeyword">{{accessLog.questionName}}</keyword></em> -> <em>{{accessLog.recordType}} <keyword :v-word="vKeyword">{{accessLog.recordValue}}</keyword></em><!-- <a href="" @click.prevent="showLog" title="查看详情"><i class="icon expand"></i></a>-->
|
<span v-if="accessLog.region != null && accessLog.region.length > 0" class="grey">[{{accessLog.region}}]</span> <keyword :v-word="vKeyword">{{accessLog.remoteAddr}}</keyword> [{{accessLog.timeLocal}}] [{{accessLog.networking}}] <em>{{accessLog.questionType}} <keyword :v-word="vKeyword">{{accessLog.questionName}}</keyword></em> -> <em>{{accessLog.recordType}} <keyword :v-word="vKeyword">{{accessLog.recordValue}}</keyword></em><!-- <a href="" @click.prevent="showLog" title="查看详情"><i class="icon expand"></i></a>-->
|
||||||
<div v-if="accessLog.nsRoutes != null && accessLog.nsRoutes.length > 0" style="margin-top: 0.3em">
|
<div v-if="(accessLog.nsRoutes != null && accessLog.nsRoutes.length > 0) || accessLog.isRecursive" style="margin-top: 0.3em">
|
||||||
<span class="ui label tiny basic grey" v-for="route in accessLog.nsRoutes">线路: {{route.name}}</span>
|
<span class="ui label tiny basic grey" v-for="route in accessLog.nsRoutes">线路: {{route.name}}</span>
|
||||||
|
<span class="ui label tiny basic grey" v-if="accessLog.isRecursive">递归DNS</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="accessLog.error != null && accessLog.error.length > 0">
|
<div v-if="accessLog.error != null && accessLog.error.length > 0" style="color:#dc143c">
|
||||||
<i class="icon warning circle"></i>错误:[{{accessLog.error}}]
|
<i class="icon warning circle"></i>错误:[{{accessLog.error}}]
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
|
|||||||
165
web/public/js/components/ns/ns-recursion-config-box.js
Normal file
165
web/public/js/components/ns/ns-recursion-config-box.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
// 递归DNS设置
|
||||||
|
Vue.component("ns-recursion-config-box", {
|
||||||
|
props: ["v-recursion-config"],
|
||||||
|
data: function () {
|
||||||
|
let recursion = this.vRecursionConfig
|
||||||
|
if (recursion == null) {
|
||||||
|
recursion = {
|
||||||
|
isOn: false,
|
||||||
|
hosts: [],
|
||||||
|
allowDomains: [],
|
||||||
|
denyDomains: [],
|
||||||
|
useLocalHosts: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (recursion.hosts == null) {
|
||||||
|
recursion.hosts = []
|
||||||
|
}
|
||||||
|
if (recursion.allowDomains == null) {
|
||||||
|
recursion.allowDomains = []
|
||||||
|
}
|
||||||
|
if (recursion.denyDomains == null) {
|
||||||
|
recursion.denyDomains = []
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
config: recursion,
|
||||||
|
hostIsAdding: false,
|
||||||
|
host: "",
|
||||||
|
updatingHost: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeHosts: function (hosts) {
|
||||||
|
this.config.hosts = hosts
|
||||||
|
},
|
||||||
|
changeAllowDomains: function (domains) {
|
||||||
|
this.config.allowDomains = domains
|
||||||
|
},
|
||||||
|
changeDenyDomains: function (domains) {
|
||||||
|
this.config.denyDomains = domains
|
||||||
|
},
|
||||||
|
removeHost: function (index) {
|
||||||
|
this.config.hosts.$remove(index)
|
||||||
|
},
|
||||||
|
addHost: function () {
|
||||||
|
this.updatingHost = null
|
||||||
|
this.host = ""
|
||||||
|
this.hostIsAdding = !this.hostIsAdding
|
||||||
|
if (this.hostIsAdding) {
|
||||||
|
var that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
let hostRef = that.$refs.hostRef
|
||||||
|
if (hostRef != null) {
|
||||||
|
hostRef.focus()
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateHost: function (host) {
|
||||||
|
this.updatingHost = host
|
||||||
|
this.host = host.host
|
||||||
|
this.hostIsAdding = !this.hostIsAdding
|
||||||
|
|
||||||
|
if (this.hostIsAdding) {
|
||||||
|
var that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
let hostRef = that.$refs.hostRef
|
||||||
|
if (hostRef != null) {
|
||||||
|
hostRef.focus()
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmHost: function () {
|
||||||
|
if (this.host.length == 0) {
|
||||||
|
teaweb.warn("请输入DNS地址")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 校验Host
|
||||||
|
// TODO 可以输入端口号
|
||||||
|
// TODO 可以选择协议
|
||||||
|
|
||||||
|
this.hostIsAdding = false
|
||||||
|
if (this.updatingHost == null) {
|
||||||
|
this.config.hosts.push({
|
||||||
|
host: this.host
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.updatingHost.host = this.host
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelHost: function () {
|
||||||
|
this.hostIsAdding = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<input type="hidden" name="recursionJSON" :value="JSON.stringify(config)"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="title">是否启用</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
<p class="comment">启用后,如果找不到某个域名的解析记录,则向上一级DNS查找。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tbody v-show="config.isOn">
|
||||||
|
<tr>
|
||||||
|
<td>从节点本机读取<br/>上级DNS主机</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" name="useLocalHosts" value="1" v-model="config.useLocalHosts"/>
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
<p class="comment">选中后,节点会试图从<code-label>/etc/resolv.conf</code-label>文件中读取DNS配置。 </p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-show="!config.useLocalHosts">
|
||||||
|
<td>上级DNS主机地址 *</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="config.hosts.length > 0">
|
||||||
|
<div v-for="(host, index) in config.hosts" class="ui label tiny basic">
|
||||||
|
{{host.host}}
|
||||||
|
<a href="" title="修改" @click.prevent="updateHost(host)"><i class="icon pencil tiny"></i></a>
|
||||||
|
<a href="" title="删除" @click.prevent="removeHost(index)"><i class="icon remove small"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
</div>
|
||||||
|
<div v-if="hostIsAdding">
|
||||||
|
<div class="ui fields inline">
|
||||||
|
<div class="ui field">
|
||||||
|
<input type="text" placeholder="DNS主机地址" v-model="host" ref="hostRef" @keyup.enter="confirmHost" @keypress.enter.prevent="1"/>
|
||||||
|
</div>
|
||||||
|
<div class="ui field">
|
||||||
|
<button class="ui button tiny" type="button" @click.prevent="confirmHost">确认</button> <a href="" title="取消" @click.prevent="cancelHost"><i class="icon remove small"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 0.5em">
|
||||||
|
<button type="button" class="ui button tiny" @click.prevent="addHost">+</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>允许的域名</td>
|
||||||
|
<td><values-box name="allowDomains" :values="config.allowDomains" @change="changeAllowDomains"></values-box>
|
||||||
|
<p class="comment">支持星号通配符,比如<code-label>*.example.org</code-label>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>不允许的域名</td>
|
||||||
|
<td>
|
||||||
|
<values-box name="denyDomains" :values="config.denyDomains" @change="changeDenyDomains"></values-box>
|
||||||
|
<p class="comment">支持星号通配符,比如<code-label>*.example.org</code-label>。优先级比允许的域名高。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="margin"></div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
{$template "/left_menu"}
|
{$template "/left_menu"}
|
||||||
|
|
||||||
<div class="right-box">
|
<div class="right-box">
|
||||||
<h3>基础设置</h3>
|
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<input type="hidden" name="clusterId" :value="cluster.id"/>
|
<input type="hidden" name="clusterId" :value="cluster.id"/>
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "/left_menu"}
|
||||||
|
|
||||||
|
<div class="right-box">
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<input type="hidden" name="clusterId" :value="clusterId"/>
|
||||||
|
|
||||||
|
<ns-recursion-config-box :v-recursion-config="config"></ns-recursion-config-box>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.success = NotifyReloadSuccess("保存成功")
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user