###暴雪爸爸開了8.0,我去保衛艾澤拉斯了,很久沒有更新。公司用的BIND做的DNS管理,採用了文本格式存儲。之前用過BIND+MYSQL+DLZ,對於後面想要自行搭建運維可視化平臺的小夥伴來說,確實很方便。但性能問題是個大問題,最後無奈採用通過Dnspython封裝的BIND接口,操作BIND的jnl文件進行動態解析。
附上一個dlz和原生bind的性能測試數據(比較老,僅供參考):
效果圖如下:
#一、 Jnl文件
jnl 文件(journal文件)是bind動態更新的時候記錄更新內容所生成的日誌文件。BIND9支持兩個授予用戶對一個域執行動態更新權限的備選方案,分別由allow-update和update-policy設定。其中allow-update 授於指定用戶對域中的任何名稱的任何的記錄更新的權利。allow-update指定哪些主機允許爲主域名服務器提交動態 DNS 更新。默認爲拒絕任何主機進行更新,詳見百度。
##二、 環境準備
- Dnspython對應你的python版本,官網http://www.dnspython.org/
- Django運行版本1.6.1
- Python運行版本2.7.1
##三、 食用過程
###1.生成TSIG key,修改named.conf添加授權,定義zone文件添加allow-update(詳見百度,這裏不具體展開)
###2.增刪改後端部分代碼
# -*- coding: utf8 -*-
import dns.tsigkeyring
import dns.update
import dns.query
import dns.resolver
keyring = dns.tsigkeyring.from_text({"youth":tsig key密碼})
up = dns.update.Update("youth.cn", keyring=keyring)
up .add("test2", 60, 'a', "192.168.183.131") #添加名稱爲test2的A記錄,TTL時間60,解析地址192.168.183.131
up.delete("test2") #刪除test2記錄
up.replace("test2", 360, "CNAME", "test3.youth.cn.") #將test2修改爲CNAME記錄,TTL時間360,CNAME地址test3.youth.cn.
dns.query.tcp(up, SERVER_IP)
###3.前端用的Metronic框架,jQuery表格插件用的dataTables,部分前端代碼如下:
<div class="page-bar">
<ul class="page-breadcrumb">
<li>
<i class="fa fa-home"></i>
<a href="../dashboard/">主頁</a>
<i class="fa fa-angle-right"></i>
</li>
<li>
<a href="../bind_list/">DNS管理系統</a>
<i class="fa fa-angle-right"></i>
</li>
<li>
<a href="../bind_list/" id="history_url">DNS管理系統彙總</a>
</li>
</ul>
</div>
<div class="portlet">
<form class="tel_search-form" method="get" action="">
<div class="row">
<div class="col-md-12">
<div class="input-group input-xlarge">
{% for i in user.groups.values %}{% ifequal i.name 'admin' %}
<div class="input-group-btn">
<select class="form-control input-small" name="bind_zone">
<option value=""> 請選擇記錄域 </option>
<option value="2"> youth.cn </option>
<option value="1"> k618.cn </option>
<option value="3"> ccyl.org.cn </option>
<option value="4"> gqt.org.cn </option>
</select>
</div>
{% else %}{% endifequal %}{% endfor %}
<div class="input-group-btn">
<select class="form-control input-small" name="bind_type">
<option value=""> 請選擇記錄類型 </option>
<option value="1"> A記錄 </option>
<option value="2"> AAAA記錄 </option>
<option value="6"> CNAME記錄 </option>
<option value="3"> MX記錄 </option>
<option value="5"> TXT記錄 </option>
<option value="4"> NS記錄 </option>
</select>
</div>
<div class="input-group-btn">
<select class="form-control input-medium" name="bind_internal_external">
<option value=""> 請選擇內外部解析類型 </option>
<option value="1"> 內部解析 </option>
<option value="2"> 外部解析</option>
</select>
</div>
<input type="text" name="search" placeholder="請輸入查詢名或者服務器IP " class="form-control input-large">
<span class="input-group-btn">
<button data-loading-text="等待提交..." class="loading-btn btn green" type="submit">查找 <i class="fa fa-search"></i></button>
<a class="btn red" href="#responsive" margin-bottomrole="button" data-toggle="modal"><span > 添加DNS解析記錄<i class="fa fa-plus"> </i></span></a>
</span>
</div>
</div>
</div>
</form>
</div>
<div class="portlet box green">
<div class="portlet-title">
<div class="caption"> <i class="icon-globe"> </i> DNS解析記錄彙總 </div>
<div class="tools"> <a href="javascript:;" class="collapse"> </a> <a href="javascript:;" class="reload"> </a> <a href="javascript:;" class="remove"> </a> </div>
</div>
<div class="portlet-body">
<table class="table table-striped table-bordered table-condensed" id="bindlist">
<thead>
<tr>
<th><b> ID </b> </th>
<th><b> 名稱 </b> </th>
<th><b> 域 </b> </th>
<th><b> 類型 </b> </th>
<th><b> 內部/外部 </b> </th>
<th><b> 解析地址 </b> </th>
<th><b> TTL </b> </th>
<th><b> 備註解析地址 </b> </th>
<th><b> 更改時間 </b> </th>
<th><b> 查看狀態 </b> </th>
<th><b> 更改操作 </b> </th>
<th><b> 刪除操作 </b> </th>
</tr>
</thead>
<tbody>
{% for bind in binds%}
<tr>
<td id={{ bind.id }}> {{ bind.id }} </td>
<td id={{ bind.bind_name }}> {{ bind.bind_name }} </td>
<td id={{bind.bind_zone_id}}>
{% ifequal bind.bind_zone_id '1' %}
<span class="label label-sm label-success">
k618.cn
</span>
{% endifequal %}
{% ifequal bind.bind_zone_id '2' %}
<span class="label label-sm label-danger">
youth.cn
</span>
{% endifequal %}
{% ifequal bind.bind_zone_id '3' %}
<span class="label label-sm label-warning">
ccyl.org.cn
</span>
{% endifequal %}
{% ifequal bind.bind_zone_id '4' %}
<span class="label label-sm label-info">
gqt.org.cn
</span>
{% endifequal %}
</td>
<td id={{ bind.bind_type_id}}>
{% ifequal bind.bind_type_id '1' %}
<span class="label label-sm label-warning">
A記錄
</span>
{% endifequal %}
{% ifequal bind.bind_type_id '6' %}
<span class="label label-sm label-info">
CNAME記錄
</span>
{% endifequal %}
{% ifequal bind.bind_type_id '3' %}
<span class="label label-sm label-success">
MX記錄
</span>
{% endifequal %}
{% ifequal bind.bind_type_id '4' %}
<span class="label label-sm label-danger">
NS記錄
</span>
{% endifequal %}
{% ifequal bind.bind_type_id '2' %}
<span class="label label-sm label-danger">
AAAA記錄
</span>
{% endifequal %}
{% ifequal bind.bind_type_id '5' %}
<span class="label label-sm label-danger">
TXT記錄
</span>
{% endifequal %}
</td>
<td id={{bind.bind_internal_external}}>
{% ifequal bind.bind_internal_external '1' %}
<span class="label label-sm label-success">
內部解析
</span>
{% endifequal %}
{% ifequal bind.bind_internal_external '2' %}
<span class="label label-sm label-warning">
外部解析
</span>
{% endifequal %}
</td>
<td id={{ bind.bind_ip}}> {{ bind.bind_ip}} </td>
<td id={{ bind.bind_ttl}}> {{ bind.bind_ttl}} </td>
<td id={{ bind.bind_intro}}> {{ bind.bind_intro}} </td>
<td> {{ bind.bind_time|date:"Y-m-d H:i:s"}} </td>
<td><a class="fa fa-eye" href="../bind_see/?bind_name={{bind.bind_name}}&bind_zone={{bind.bind_zone}}&bind_ip={{bind.bind_ip}}"></a></td>
<td><a class="fa fa-edit" href="#responsives2" data-toggle="modal"></a></td>
<td><a class="fa fa-trash-o" href="#responsivess" data-toggle="modal"></a></td>
{% endfor %}
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal fade" id="responsive" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button>
<h3 id="myModalLabel"> 添加DNS解析記錄 </h3>
</div>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<div class="modal-body">
<div class="form-group">
<label class="control-label col-md-3"> 名稱 </label>
<div class="col-md-5">
<input type="text" class="form-control" placeholder="例如:cms" name="bind_name">
</div>
</div>
<div class="form-group" >
<label class="control-label col-md-3"> TTL </label>
<div class="col-md-5">
<input type="text" class="form-control" placeholder="例如:3600" name="bind_ttl">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> Zone域 </label>
<div class="col-md-5">
<select class="form-control input-medium select2me select2-offscreen" name="bind_zone">
<option value="2"> youth.cn </option>
<option value="1"> k618.cn </option>
<option value="3"> ccyl.org.cn </option>
<option value="4"> gqt.org.cn </option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 類型 </label>
<div class="col-md-5">
<select class="form-control input-medium select2me select2-offscreen" name="bind_type" onchange="add_bind_intro_hidden(this)">
<option value="1"> A記錄 </option>
<option value="2"> AAAA記錄 </option>
<option value="6"> CNAME記錄 </option>
<option value="3"> MX記錄 </option>
<option value="5"> TXT記錄 </option>
<option value="4"> NS記錄 </option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 解析地址 </label>
<div class="col-md-5">
<input type="text" class="form-control" placeholder="例如:123.103.56.246" name="bind_ip">
</div>
</div>
<div class="form-group" id="add_bind_intro" style="display:none;">
<label class="control-label col-md-3"> 備註解析地址 </label>
<div class="col-md-5">
<input type="text" class="form-control" placeholder="例如:123.103.56.246" name="bind_intro">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 解析類型 </label>
<div class="col-md-5">
<select class="form-control input-medium select2me select2-offscreen" name="bind_internal_external" onchange="edit_bind_internal_external_hidden(this)">
<option value="1"> 內部解析 </option>
<option value="2"> 外部解析 </option>
</select>
</div>
</div>
<div class="form-group" id="add_bind_url_mitors" style="display:none;">
<label class="control-label col-md-3">URL監控</label>
<div class="col-md-5">
<div class="basic-toggle-button" >
<input type="checkbox" class="make-switch" id="add_url_mitor" checked="checked" data-size="small"/>
<input type="hidden" name="add_url_mitors" value="true" id="add_url_mitors"/>
</div>
</div>
</div>
<div class="form-group" id="add_bind_syncs" style="display:none;">
<label class="control-label col-md-3">同步網宿節點</label>
<div class="col-md-5">
<div class="basic-toggle-button" >
<input type="checkbox" class="make-switch" id="add_sync" checked="checked" data-size="small"/>
<input type="hidden" name="add_syncs" value="true" id="add_syncs"/>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button data-loading-text="等待提交..." class="loading-btn btn green" type="submit" name="submit"> 確認執行 </button>
<button class="btn red" data-dismiss="modal" aria-hidden="true"> 取消執行 </button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="responsivess" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button>
<input type="hidden" id="del_name">
</div>
<form action="" method="get" class="form-horizontal">
{% csrf_token %}
<div class="modal-body">
<div class="form-group">
<div class="col-md-5">
<span class="label label-danger">注意:刪除解析記錄,相應的監控記錄也會一併刪除!!</span>
</div>
</div>
</div>
<div class="modal-footer">
<label class="control-label"> </label>
<div class="controls">
<button data-loading-text="等待提交..." class="loading-btn btn green" type="submit" name="submit"> 確認執行 </button>
<button class="btn red" data-dismiss="modal" aria-hidden="true"> 取消執行 </button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="responsives2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button>
<h3 id="myModalLabel"> 修改DNS解析記錄 </h3>
</div>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<div class="modal-body">
<div class="form-group" type="hidden">
<div class="col-md-5">
<input type="text" id="edit_bind_id">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 名稱 </label>
<div class="col-md-5">
<input type="text" id="edit_bind_name">
</div>
</div>
<div class="form-group" >
<label class="control-label col-md-3"> TTL </label>
<div class="col-md-5">
<input type="text" id="edit_bind_ttl">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> Zone域 </label>
<div class="col-md-5">
<select class="form-control input-medium select2me select2-offscreen" name="bind_zone" id="edit_bind_zone">
<option value="2"> youth.cn </option>
<option value="1"> k618.cn </option>
<option value="3"> ccyl.org.cn </option>
<option value="4"> gqt.org.cn </option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 類型 </label>
<div class="col-md-5">
<select class="form-control input-medium select2me select2-offscreen" name="bind_type" id="edit_bind_type" onchange="edit_bind_intro_hidden(this)">
<option value="1"> A記錄 </option>
<option value="2"> AAAA記錄 </option>
<option value="6"> CNAME記錄 </option>
<option value="3"> MX記錄 </option>
<option value="5"> TXT記錄 </option>
<option value="4"> NS記錄 </option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"> 解析地址 </label>
<div class="col-md-5">
<input type="text" id="edit_bind_ip">
</div>
</div>
<div class="form-group" id="edit_bind_intro" style="display:none;">
<label class="control-label col-md-3"> 備註解析地址 </label>
<div class="col-md-5">
<input type="text" id="edit_bind_intros">
</div>
</div>
</div>
<div class="modal-footer">
<button data-loading-text="等待提交..." class="loading-btn btn green" type="submit" name="submit"> 確認執行 </button>
<button class="btn red" data-dismiss="modal" aria-hidden="true"> 取消執行 </button>
</div>
</form>
</div>
</div>
</div>
這塊做了一個異步的查詢,其實就是點擊+號,能返回到這個域名綁定的公網IP所對應的主機,效果圖如下:
var TableAdvanced = function () {
var initTable4 = function () {
var table = $('#bindlist');
var nCloneTh = document.createElement('th');
nCloneTh.className = "table-checkbox";
var nCloneTd = document.createElement('td');
nCloneTd.innerHTML = '<span class="row-details row-details-close"></span>';
table.find('thead tr').each(function () {
this.insertBefore(nCloneTh, this.childNodes[0]);
});
table.find('tbody tr').each(function () {
this.insertBefore(nCloneTd.cloneNode(true), this.childNodes[0]);
});
var oTable = table.dataTable({
// Internationalisation. For more info refer to http://datatables.net/manual/i18n
"language": {
"aria": {
"sortAscending": ": activate to sort column ascending",
"sortDescending": ": activate to sort column descending"
},
"emptyTable": "未有相關數據",
"info": "當前顯示 _START_ 到 _END_ 條,共 _TOTAL_ 條記錄。",
"infoEmpty": "當前顯示0到0條,共0條記錄",
"infoFiltered": "(數據庫中共爲 _MAX_ 條記錄)",
"lengthMenu": "顯示 _MENU_ 記錄",
"search": "模糊查詢:",
"zeroRecords": "對不起,查詢不到任何相關數據",
"oPaginate": {
"sFirst": "首頁",
"sPrevious": " 上一頁 ",
"sNext": " 下一頁 ",
"sLast": " 尾頁 "
}
},
"columnDefs": [{
"orderable": false,
"targets": [0]
}],
"order": [
[9, 'dec']
],
"lengthMenu": [
[5, 15, 20, -1],
[5, 15, 20, "All"] // change per page values here
],
// set the initial value
"pageLength": 10
});
var tableWrapper = $('#sample_4_wrapper'); // datatable creates the table wrapper by adding with id {your_table_jd}_wrapper
var tableColumnToggler = $('#sample_4_column_toggler');
/* modify datatable control inputs */
tableWrapper.find('.dataTables_length select').select2(); // initialize select2 dropdown
table.on('click', ' tbody td .row-details', function () {
var nTr = $(this).parents('tr')[0];
if (oTable.fnIsOpen(nTr)) {
$(this).addClass("row-details-close").removeClass("row-details-open");
oTable.fnClose(nTr);
} else {
var ip = $(this).parent().parent().find('td').eq(6).attr("id");
var type = $(this).parent().parent().find('td').eq(4).attr("id");
var intro = $(this).parent().parent().find('td').eq(8).attr("id");
$(this).addClass("row-details-open").removeClass("row-details-close");;
fnFormatDetails(nTr, $(this).attr("data_id"),ip,type,intro);
}
});
function fnFormatDetails(nTr, pdataId, ip ,type ,intro) {
var aData = oTable.fnGetData(nTr);
//根據配置Id 異步查詢數據
$.ajax({
type:'get',
url:"../bind_host_get/?ip="+ip+"&type="+type+"&intro="+intro,
data:{"pdataId":pdataId},
dataType:"json",
async:true,
beforeSend:function(xhr){//信息加載中
oTable.fnOpen( nTr, '<span id="configure_chart_loading"><img src="../assets/global/img/input-spinner.gif"/> 詳細信息加載中...</span>', 'details' );
},
success:function (obj){
var sOut = '<table class="table table-striped table-bordered table-hover">';
for(var id in obj){
sOut += '<tr><td>'+id+'</td><td>' + obj[id] + '</td></tr>';
}
sOut+='</table>';
oTable.fnOpen( nTr,sOut, 'details' );
},
error: function(){//請求出錯處理
oTable.fnOpen( nTr,'加載數據超時', 'details' );
}
});
}
/* handle show/hide columns*/
$('input[type="checkbox"]', tableColumnToggler).change(function () {
/* Get the DataTables object again - this is not a recreation, just a get of the object */
var iCol = parseInt($(this).attr("data-column"));
var bVis = oTable.fnSettings().aoColumns[iCol].bVisible;
oTable.fnSetColumnVis(iCol, (bVis ? false : true));
});
}
return {
//main function to initiate the module
init: function () {
if (!jQuery().dataTable) {
return;
}
console.log('me 1');
initTable4();
console.log('me 2');
}
};
}();
####這裏踩過的坑:
最終公司的DNS慘遭了30G的DD,導致運營商都跟着一起倒黴,後續將NS解析遷移至網宿的雲DNS平臺,我的平臺還是通過網宿的雲DNS平臺所提供的接口API進行域名解析,BIND只作爲內網解析及解析記錄彙總(即選擇外部解析後,解析記錄將存儲在我的內部平臺上並推送記錄到網宿節點,這也是爲了將來萬一換廠家,直接推送全部記錄即可)
####URL監控用的Openfalcon做的,後續會慢慢補上。。。