mysql的安装目录里有support-files,里面有几份默认的配置
分别是 huge large medium 等,还有高压力的InnoDB的参考:
[root@aslibra support-files]# grep -v ^# my-huge.cnf
key_buffer = 384M
table_cache = 512
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 32M
thread_concurrency = 8
[root@aslibra support-files]# grep -v ^# my-large.cnf
key_buffer = 256M
table_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
thread_concurrency = 8
[root@aslibra support-files]# grep -v ^# my-medium.cnf
key_buffer = 16M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
[root@aslibra support-files]# cat my-innodb-heavy-4G.cnf|grep -v ^#|grep -v "^$"
back_log = 50
max_connections = 100
max_connect_errors = 10
table_cache = 2048
max_allowed_packet = 16M
binlog_cache_size = 1M
max_heap_table_size = 64M
sort_buffer_size = 8M
join_buffer_size = 8M
thread_cache_size = 8
thread_concurrency = 8
query_cache_size = 64M
query_cache_limit = 2M
ft_min_word_len = 4
default_table_type = MYISAM
thread_stack = 192K
transaction_isolation = REPEATABLE-READ
tmp_table_size = 64M
log-bin=mysql-bin
log_slow_queries
long_query_time = 2
log_long_format
server-id = 1
key_buffer_size = 32M
read_buffer_size = 2M
read_rnd_buffer_size = 16M
bulk_insert_buffer_size = 64M
myisam_sort_buffer_size = 128M
myisam_max_sort_file_size = 10G
myisam_max_extra_sort_file_size = 10G
myisam_repair_threads = 1
myisam_recover
一般情况下,自己根据机器的情况,复制一份到默认的配置文件的位置,替代默认配置
比如纯数据库的机器,有1-2G以上的内存,可以拷贝huge的那份,要不然默认配置效率不高,比如查询时容易用到磁盘做临时文件,这份可以提高内存的使用率。
对比一下几份配置的同一参数:
key_buffer = 16M
key_buffer = 256M
key_buffer = 384M
myisam_sort_buffer_size = 8M
myisam_sort_buffer_size = 64M
myisam_sort_buffer_size = 64M
myisam_sort_buffer_size = 128M
query_cache_size= 16M
query_cache_size = 32M
query_cache_size = 64M
read_buffer_size = 256K
read_buffer_size = 1M
read_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 512K
read_rnd_buffer_size = 4M
read_rnd_buffer_size = 8M
read_rnd_buffer_size = 16M
sort_buffer_size = 512K
sort_buffer_size = 1M
sort_buffer_size = 2M
sort_buffer_size = 8M
table_cache = 64
table_cache = 256
table_cache = 512
table_cache = 2048
没有细节的技术可以解析,细节信息还是得查资料,这里只是列举对比一下,也许可以提醒大家使用内存和修改配置来优化mysql
编译加-enable-delay-pools选项
添加以下行:
delay_pools 1
delay_class 1 1
delay_access 1 allow all
delay_parameters 1 50000/50000 # 限制网速在50K以内
delay_initial_bucket_level 50
--------------------------------------
今天测试了一下squid使用delay_pools来对源网站的访问进行限速.非常好用,如下
使用squid建二个源网站
1
2
3
4
5
6
|
acl php-oa url_regex -i ^http: // .*php-oa.com/.*
acl sudo -u url_regex -i ^http: // .* sudo -u.com/.*
http_access allow mysite
http_access allow sudo -u
http_access deny all
icp_access allow all
|
下面开始正文,我们要用到squid中的delay_pools,delay_pools里可以定义多个容器(多个源定义多个),而这个容器就是我们要控制的带宽,当容器到达所设定的容量时,这个容器的所有者就无法超过我们所设定的带宽限制.
开始设置squid的delay_pools
01
02
03
04
05
06
07
08
09
10
11
|
delay_pools 2
delay_class 1 2
delay_access 1 allow php-oa
delay_access 1 deny all
delay_parameters 1 64000 /64000 64000 /32000
delay_class 2 1
delay_access 2 allow sudo -u
delay_access 2 deny all
delay_parameters 2 32000 /16000
|
class定义:
class类型1为单个IP地址流量
class类型2为C类网段中的每个IP地址流量
class类型3为B类网段中的每个C类网段中的每个IP地址流量
delay_parameters语法:
类型1只有一个总带宽流量实际也就是这个IP地址的流量
delay_parameters pool total
例:delay_parameters 1 64000/64000
类型2有两个带宽流量参数,第一个为整个C类型网段流量,第二个为每个IP流量
delay_parameters pool tatal per-host
例:delay_parameters 1 -1/-1 64000/64000
类型3有三个带宽流量参数,第一个为整个B类网总流量,第二个为每个B类网段中的C类网段总流量,第三个为了B类网段中每个C类网段中的每个IP流量
delay_parameters pool total network per-host
例:delay_parameters 1 -1/-1 -1/-1 64000/64000
注: -1/-1表示流量无限制.每个delay_parameters的数值是由"回源站的速度/客户最大下载速度"组成
另外,对HIT的文件没有作用
----------------------------
UserDefine
acl vip src 192.168.24.0/255.255.255.0
acl normal_users src 192.168.11.232 192.168.11.211 192.168.11.231
acl vip_sc200 src 192.168.23.211 192.168.23.112
acl banneduser src 192.168.9.100
acl vip_me src 192.168.9.30
acl test src 192.168.100.250
acl all src 0.0.0.0/0
# define download files extension
acl disable_extension urlpath_regex -i \.mp3$ \.avi$ \.rmvb$ \.rm$ \.ra$ \.ram$ \.mpe$ \.smi$ \.mpeg$ \.wmv$ \.wma$ \.3gp$ \.td$ \.t
# define disable site dstdomain files.
# define disable ip for domain file
#Port Define
http_port 88
cache_mgr 5111
visible_hostname ifc-proxy
#HttpAccess
http_access allow vip
http_access allow vip_me
http_access deny disable_extension
#MaxConn Define
acl num_conn maxconn 5
acl num_conn2 maxconn 20
#HttpAccess MaxConn Define
http_access deny normal_users num_conn
http_access deny test num_conn
http_access deny vip_sc200 num_conn2
#SpeedControl
delay_pools 4
delay_class 1 3
delay_class 2 3
delay_class 3 2
delay_class 4 3
delay_access 1 allow vip_sc200
delay_access 2 allow normal_users
delay_access 3 allow test
delay_access 4 allow all
delay_parameters 1 128000/128000 -1/-1 32000/64000
delay_parameters 2 64000/64000 -1/-1 8000/64000
delay_parameters 3 64000/64000 8000/64000
delay_parameters 4 1/1 1/1 1/1
前面一长段可以不看,看最后的一段,下面是注释
delay_pools 4 //表示有4个限制池,或者说对4种不同的目标限制
delay_class 1 3
delay_class 2 3
delay_class 3 2
delay_class 4 3 //上面的4行分别声明了四个池的类型,池1,2,4用于B类网段控制,池3用于C类网段控制,另外如果声明类型为class n 1表示控制单个ip地址
delay_access 1 allow vip_sc200
delay_access 2 allow normal_users
delay_access 3 allow test
delay_access 4 allow all //这几行分别对一开始定义的四个用户组进行限速,分别应用1,2,3,4号限制池
delay_parameters 1 128000/128000 -1/-1 32000/64000
delay_parameters 2 64000/64000 -1/-1 8000/64000
delay_parameters 3 64000/64000 8000/64000
delay_parameters 4 1/1 1/1 1/1
这四行分别声明了1,2,3,4号限制池的速度限制大小,比如第一个,我们前面声明的是B类网段,所以他的格式大概就是
delay_parameters 限制池号 本池最大速度 网段最大速度 单个ip最大速度
至于限制C类段的就少个网段最大速度,格式为
delay_parameters 限制池号 本池最大速度 单个ip最大速度
可能说的不太清楚,如果看不懂的可以参考下面的内容
关于设定SQUID带宽限制和流量整形,刻利用squid.conf种的delay_pools字段来完成.
delay pools里的bucket就像是一个容器,而这个容器就是squid要控制带宽用的,当容器到达所设定的容量时,这个容器的所有者就无法超过我们所设定的带宽限制,所有的bucket则称之为unified bucket.
Class分为三种:
(1)Class 1:包含一个unified bucket,而这个bucket是给这个class里所定义的host使用.
(2)Class 2:包含一个unified bucket和255个buckets,每一个bucket分配给8bit网络的使用者(255 hosts)使用IPv4 class C).
(3)Class 3:包含255个buckets,每一个bucket分配给16bit网络的使用者(65535 hosts)使用(IPv4 class B).
(1)Class 1:contains a single unified bucket which is used for all requests from hosts subject to the pool
(2)Class 2:contains one unified bucket and 255 buckets, one for each host on an 8-bit network (IPv4 class C)
(3)Class 3:contains 255 buckets for the subnets in a 16-bit network, and individual buckets for every host on these networks (IPv4 class B)
推测:如果ACL只定义一个class C字段,要限制每个host的单一带宽,可以使用Class 2来做;但如果ACL有定义好几个class C字段,使用Class 3可再对各个class C字段做个别的总带宽限制
delay_parameters语法:
class 1 delay pool;
delay_parameters pool total
class 2 delay pool;
delay_parameters pool tatal per-host
class 3 delay pool;
delay_parameters pool total network per-host
每个delay_parameters的数值是由restore(byte/sec)/max(bytes)组成,restore是表示以bytes/sec的速度下载object到bucket里,而max则表示bucket的bytes值.
备注1:如果要设定为unilit speed的话,将数值设定为-1即可
备注2:SQUID FAQ中有提到,建议max至少要设为restore的两倍(It is recommended that the maximum is at least twice the restore value)
[设定文档格式说明]
acl all src 0.0.0.0/0.0.0.0
acl lan src 192.168.1.0/255.255.255.0 # 定义 ACL
delay_pools n # 总共有几个 delay_pools
delay_class n1 1 # 第 n1 个 delay_pool 的种类是 Class 1
delay_class n2 3 # 第 n2 个 delay_pool 的种类是 Class 3
delay_class n3 2 # 第 n3 个 delay_pool 的种类是 Class 2
delay_access n1 allow lan
delay_access n1 deny all # 定义 delay_pool n1 的 access rule
delay_parameters n1 64000/64000 # 定义 delay_pool n1 的速度限制,依 class 的不同有不同的定义方式 (请参照上面的说明)
[范例说明]
1. 限制限制带宽为 512 Kbps
acl all src 0.0.0.0/0.0.0.0 # might already be defined
delay_pools 1
delay_class 1 1
delay_access 1 allow all
delay_parameters 1 64000/64000 # 512 kbits == 64 kbytes per second
2. 限制限制单一的带宽为 128 Kbps
acl only128kusers src 192.168.1.0/255.255.192.0
acl all src 0.0.0.0/0.0.0.0
delay_pools 1
delay_class 1 3
delay_access 1 allow only128kusers
delay_access 1 deny all
delay_parameters 1 64000/64000 -1/-1 16000/64000
3. 对某些特定的网站设置不通的带宽限制 (自己尝试一下,如果有错误请自行修改)
acl lan_use src 192.168.1.0/255.255.255.0 # 设置 LAN 使用者的 ACL
acl kkbox dstdomain .kkbox.com.tw # 设置特定域名的 ACL
delay_pools 2 # 设置两个 delay_pools
delay_class 1 1 # 第一个是 Class 1 的,用來限制总带宽
delay_class 2 2 # 第二个是 Class 2 的,用来限制单一的带宽
delay_access 1 allow kkbox
delay_access 1 deny all
delay_access 2 allow lan_use
delay_access 2 deny all
delay_parameters 1 64000/64000 # 不限制指定域名的单一带宽,但对总带宽速作限制
delay_parameters 2 64000/64000 10000/50000 # 限制 LAN 的所有使用者单一带宽,并对总的带宽作以限制
作者: abelyang <abelyang{at}twnic{dot}net{dot}tw>
version: 1.0
最后修正时间: 2007/07/28 00:10
转载时请保持此一宣告
1.前言
目前动态 DNS 两大主流,一个是 BIND (ISC),另一个就是套接 DB 的 DNS 如 PowerDNS (或 mydns)
等,两种方式各有好坏,主要是因为 BIND 会有一些复杂性,但效果非常好,而 PowerDNS 则是很简单,
但相对的它不能承受大量查询,主要原因在于数据库上先天的限制. 本文主要为介绍 BIND 之动态
DNS 做法,而这个做法之最重要重点则在于nsupdate 这个指令及 IXFR (incremental zone transfer
request),是不同于传统的 AXFR (full zone transfer),IXFR 在做 Zone Transfer (DNS 的同步机制)
时,会以差异化的部份进行同步, 而 AXFR 则是以整个 Zone 进行同步.DDNS 主要由 RFC 2136 构成,
建议若您要对 DDNS 有一定深入的了解,可以阅读这篇 RFC 以了解更多重要的信息
(1034 1035 1995 是 2136 的基础)
本文适用于对 DNS 巳有一定了解的朋友,若是不甚清楚建议您可先参考 TWNIC 所做的讲义:
http://dns-learning.twnic.net.tw/DNS94/
如果你想对 nsupdate + key 的方法有更深入的了解可以参考
http://www.study-area.org/tips/tipsfr1.htm
或参考 isc bind 的文件有最详细的解说
http://www.isc.org/sw/bind/arm93/Bv9ARM.pdf
本文不讨论 view 的情形,若是 view 情形您必需从 view 的 match-client 去更新或是使用不同
的 key,所以建议您多参考 isb bind 的文件,虽然辛苦些,但数据绝对是最官方最正确的
2. 必要的信息及知识
本文的范例以 Shell Script 做成,重点在于原理,采用什么工具或做法完全视您个人的能力.以下
就一些重点进行说明.
2.1 BIND 动态更新
基本上在 BIND8,BIND9 都是支持 nsupdate 的,但这里面要注意的是 BIND8 在8.3.X 后才支援
IXFR,而 BIND9 则都支持,所以若您的 Server 在 8.3.0 前的版本,那就不建议了,更何况这个以
前的版本多多少少都有许多安全性的问题.
2.1.1 nsupdate:
bind 要开 allow-update 选项,让你的程序可以来执行更新指令,allow-update 选项可以是 IP 或
key,而本文仅就 IP进行介绍,若用 Key 对有些朋友来说可能会变得稍复杂些了
# named.conf
# 其它略
zone "dyndns.twnic.tw" {
type master;
file "dyndns.twnic.tw";
allow-update {127.0.0.1;}; # 开放 127.0.0.1 进行动态更新
allow-transfer { slave_ip;127.0.0.1;}; # slave 主机,可能一部或多部,若无请写 none
};
以上是开放让 127.0.0.1 进行动态更新,动态更新有其指令,详细您可看看 nsupdate man page
(man nsupdate),以下仅以最常用的进行说明:
#nsupdate
[root@eai1 dyndns]# nsupdate
> server 127.0.0.1
> zone dyndns.twnic.tw
> update delete user1.dyndns.twnic.tw A 211.72.210.249
> update add user1.dyndns.twnic.tw A 211.72.210.251
ttl 'A': not a valid number # 这个例子是错误示范,加一笔记录要有 TTL 值
> update add user1.dyndns.twnic.tw 60 A 211.72.210.251
> show
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0
;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; UPDATE SECTION:
user1.dyndns.twnic.tw. 0 NONE A 211.72.210.249
user1.dyndns.twnic.tw. 60 IN A 211.72.210.251
> send
> quit
server 指向某一台 NameServer 进行 update 操作
zone 修改某个 zone file
update delete 进行 update 的 delete 动作,这个指令格式是
update delete FQDN TYPE RDATA,如果有多笔相同的 A
记录或不同的 MX 记录要删除某一笔需将 RDATA 补上,
若没有 RDATA 则表示这个 FQDN 的这个 TYPE 都要删除
(TYPE 即是 A,MX,PTR,SOA,NS..等,RDATA 就是 TYPE 后
接的东西,如 A 的 RDATA 是 IP 而 MX 的 RDATA 是 优
先权 FQDN)
update add 进行记录的增加,操作如同 delete, 但是一定要有
TTL 值,且必需明确写出 RDATA
show 这只是操作后要显示进行了那些 update 指令
send 这个代表要把整个 update 指令送给 server,操作 update
时数据不是马上送出的,所以 update 可以很多行,最后
nsupdate 看到 send 时,才会将整个所有 update 送出,
而 update 使用 port 53/udp 若送出的数据量 (DNS packet)
大于 512 bytes,则会 truncate 而改使用 53/tcp,这是您
需要注意的地方,而只要您有 send, 则 SOA 记录的 serial
会自动加1,以期让 slave 来进行同步,所以过多的 send 可
能造成过多的 traffic
2.1.2 zone file 及日志文件
如果您进行了 nsupdate 的操作,则原来 directory 所指的目录将会产生一些日志文件,这个日志文件即为
zone_name.jnl (directory 习惯上都设在 /var/named , 您自己必要注意 named 程序要有写入的权限,
chroot 状况等)
# 显示 dyndns.twnic.tw zone file 内容
[root@eai1 named]# cat /var/named/dyndns.twnic.tw
$TTL 86400 ; 1 day
@ IN SOA twnic.net.tw. snw.twnic.net.tw. (
2006073267 ; serial
7200 ; refresh (2 hours)
1800 ; retry (30 minutes)
2419000 ; expire (3 weeks 6 days 23 hours 56 minutes 40 seconds)
300 ; minimum (5 minutes)
)
NS ns2.dyndns.twnic.tw.
NS eai1.twnic.tw.
ns2 A 203.73.24.204
; 如果别人在查询时,我们有这个记录则响应这个记录的 IP,若没有这个记录代表
; 这个网站没有上线,所以此时我们可以建立一笔 wildcard 记录,指向自己的说
; 明网站,以供 user 识别这个网站没有上线,而这笔 wildcard 的记录 TTL 时间
; 不能太长,以免别的 DNS Cache 了这资料
* 0 A 211.72.210.251
# 目录里的东西
[root@eai1 named]# ls -la /var/named/
总计 128
drwxr-xr-x 2 named named 4096 7月 27 09:25 .
drwxr-xr-x 20 root root 4096 3月 13 16:50 ..
-rw-r--r-- 1 named named 451 7月 27 09:25 dyndns.twnic.tw
-rw-r--r-- 1 named named 104177 7月 27 10:01 dyndns.twnic.tw.jnl
-rw-r--r-- 1 named named 195 7月 4 2001 localhost.zone
-rw-r--r-- 1 named named 2851 10月 17 2003 named.ca
我们可以看到这个 .jnl 的产生,这个 .jnl 档是不能随便删除,因为它等于是 dyndns.twnic.tw 的补
充数据,而这些补充资料在 DNS reload/restart 时, named 还会在把它读进来,所以动态更新后的数据,
并不会随着 dns 重启后而消失,如果你想让现在整个 zone 文件出现所有的记录,那可以 rndc stop 来停止
dns, 此时 named 会把 .jnl数据写入原来的 zone file,不过这种方式一般来说较不建议,因为我们的 zone
file 只要存一个样版 (template),其它的东西都是临时性的. 而若你想知道现在整个 zone 的内容,在可
以做 zone transfer 的主机上(如上例为 slave_ip及 127.0.0.1), 以 dig 指令来执行 axfr:
[root@eai1 dyndns]# dig @127.0.0.1 dyndns.twnic.tw axfr
; <<>> DiG 9.3.0 <<>> @127.0.0.1 dyndns.twnic.tw axfr
;; global options: printcmd
dyndns.twnic.tw. 86400 IN SOA twnic.net.tw. snw.twnic.net.tw. 2006073528 7200 1800 2419000 300
dyndns.twnic.tw. 86400 IN NS ns2.dyndns.twnic.tw.
dyndns.twnic.tw. 86400 IN NS eai1.twnic.tw.
*.dyndns.twnic.tw. 0 IN A 211.72.210.251
ns2.dyndns.twnic.tw. 86400 IN A 203.73.24.204
user1.dyndns.twnic.tw. 60 IN A 211.72.210.248
user1.dyndns.twnic.tw. 60 IN MX 10 user1.dyndns.twnic.tw.
# 以下略
...
2.设定 NameServer 仅进行差异化的同步
Master/Slave 要进行 zone file 的同步,而 ddns server 若只有一部是可以不用考虑这些问题的,但是若有两
部以上的 DNS Server, 就需要考虑到同步的进行方式,若 zone file 的总数据量小,采用什么同步方式是无所
谓的,但若数据量多,或是经常处在变动状况,那差异化的同步就会显得很重要,因为它可以让所有的 DNS 在短时
间内全部同步完成,BIND 支持 IXFR 后,其预设即是采用 IXFR, 若没有 IXFR (update) 时,则采用 AXFR,所以不
需要对 IXFR 进行额外设定,但为使大家了解其参数,本处还是举例来进行说明,好让大家能够更了解
# master DNS's named.conf
key "rndc-key" {
algorithm hmac-md5;
secret "HpXtFRFdLaRPFjpZokIwusyezyyRNjxhcafCfmktWNyGkDFzHAXlpTZQtVLc";
};
controls {
inet 127.0.0.1 port 953
allow { 127.0.0.1; } keys { "rndc-key"; };
};
options {
directory "/var/named";
pid-file "/var/run/named/named.pid";
allow-transfer { none; };
provide-ixfr yes; # 提供 slave 主机以 IXFR 同步,default yes
request-ixfr yes; # slave 以 IXFR 向 master 进行同步,default yes
recursion no; # 不允许递归查询
};
zone "0.0.127.in-addr.arpa" {
type master;
file "named.local";
};
zone "." {
type hint;
file "named.ca";
};
zone "dyndns.twnic.tw" {
type master;
file "dyndns.twnic.tw";
max-journal-size 500k; # 设定日志文件大小
allow-transfer { 203.73.24.204;127.0.0.1;}; # 可做 ixfr/axfr 的来源 IP,必需写上 slave,
# 127.0.0.1 是方使我们自己查看 zone file 现况
also-notify {203.73.24.205;211.72.210.251}; # 额外的同步主机,这可能是 hot site 备份主机
allow-update { 127.0.0.1;}; # 允许动态更新的来源
};
上述的东西相信只要对 BIND DNS 有一定了解的朋友应该都是没有问题的,较不常出现的项目我都加上了的批注以利
大家了解,而 slave 的设法都同于 master, 只有在 zone 的部份稍有不同:
# slave DNS's named.conf
# 其它设定皆同上,只有 zone ...稍有不同,同于一般的 slave zone,不需要再开 allow-update (default none)
zone "dyndns.twnic.tw" {
type slave;
masters {211.72.210.249;};
file "dyndns.twnic.tw";
allow-transfer { none;};
};
所以从上述我们可以知道 DDNS for Master/Slave 您只要对 master 进行 update,每次的 update 送出 (send)
会使该zone 的序号加一,只要 zone 有更新 , dns 会送出 notify 讯息给所有的 NS 主机(NS 记录上所列的名称
服务器),及可能的 also-notify 对象,使 slave 主机知道要进行同步,同步时优先采用 IXFR,若 master 不支持
IXFR 则改使用 AXFR,以达到即使更新,及时同步的效果
此外,有些做 DDNS 的公司可能对 IXFR 不了解,而是把所有的 zone type 都设成了 MASTER,然后对这些 NameServer
进行 nsupdate , 这种做法也是可以的,不过中间若漏了一步或那一台少做了一件事,那两边的资料就会不一致,导致
可能同一个名称会有不同的解析结果 (例如 gnway.net 做法)
--------------------------------------------------------------------------------
abel 回复于:2006-07-28 14:52:21
3. DDNS 的前端及后台控制范例
说是范例主要是让大家参考原理,并没有必要一定都用我的方式,只要前面讲的东西您可以了解,程控的部份
仅是末节,以下仅列出我所用的方式供大家参考
3.1 MYSQL table
主要由三个表构成,分别为 RR (Resource Record), RR_LOG (旧资料,建议您依状况适当保存),USER (user 认证)
CREATE TABLE RR (
SN int(20) NOT NULL auto_increment,
USERNAME varchar(64) NOT NULL default '',
FQDN varchar(64) NOT NULL default '',
TTL int(5) NOT NULL default '60',
TYPE varchar(10) NOT NULL default '',
RDATA varchar(64) NOT NULL default '',
CREATE_TIME timestamp(14) NOT NULL,
PRIMARY KEY (SN),
KEY USERNAME (USERNAME),
KEY FQDN (FQDN),
KEY TTL (TTL),
KEY TYPE (TYPE),
KEY CREATE_TIME (CREATE_TIME)
) TYPE=MyISAM;
--
-- Table structure for table 'RR_LOG'
--
CREATE TABLE RR_LOG (
SN int(20) NOT NULL default '0',
USERNAME varchar(64) NOT NULL default '',
FQDN varchar(64) NOT NULL default '',
TTL int(5) NOT NULL default '60',
TYPE varchar(10) NOT NULL default '',
RDATA varchar(64) NOT NULL default '',
CREATE_TIME varchar(14) default NULL,
PRIMARY KEY (SN),
KEY USERNAME (USERNAME),
KEY FQDN (FQDN),
KEY CREATE_TIME (CREATE_TIME)
) TYPE=MyISAM;
--
-- Table structure for table 'USER'
--
CREATE TABLE USER (
SN int(20) NOT NULL auto_increment,
USERNAME varchar(64) NOT NULL default '',
PASSWD varchar(64) NOT NULL default '',
EMAIL varchar(64) NOT NULL default '',
MEMO varchar(255) NOT NULL default '',
PRIMARY KEY (SN),
UNIQUE KEY USERNAME (USERNAME)
) TYPE=MyISAM;
3.2 dyndns.cfg 设定档
这个设定文件主要为了给 CGI 程序及产生 nsupdate 的程序 (dyndns-cron.sh) 所使用,透过 eval 方式来执行,
以取得共同的变量
# mysql host/db/user/password
DBHOST=localhost
DBNAME=dyndns
DBUSER=UserName
DBPASS=Your_Passwd
MYSQL="mysql $DBNAME -h $DBHOST -u $DBUSER -p$DBPASS"
# dyndns domain
DOMAIN=dyndns.twnic.tw
# Master IP
DYNDNS_MASTER=127.0.0.1
# nsupdate command file
CMD_FILE=/tmp/nsupdate.cmd
# update freqency
UPD_FREQ=15
# RR valid time (seconds),default 20 mins
RR_ALIVE=1200
3.3 dyndns.cgi CGI 程序
这个 CGI 主要用于接收 USER 端来的信息,验证通过后即为把 USERNAME.DOMAIN 数据,A/MX 及对应 IP 存入
Table RR 中,此外这个 CGI 以 shell script 做成,可以于多数人的环境执行 (chmod 755 及目录的 CGI 执
行权限 ExecCGI 莫忘)
#!/bin/sh
echo -ne "Content-Type: text/html\n\n"
if [ -n "$QUERY_STRING" ];then
# 取得 QUERY_STRING,以下这个作法是危险的,因为没有检查数据的正确性就 eval
# 我的用意只在于说明作法
eval `echo "$QUERY_STRING" | sed "s/&/;/g"`
# 读取设定文件,这个路径您需要自行调整
eval `cat /home/abelyang/dyndns/dyndns.cfg `
sql0="select 1 from USER where USERNAME='$LOGIN' and PASSWD='$PASSWD'"
res=`echo $sql0 | $MYSQL `
# 如果 USER 密码正确, ${#res} 应为2,不对则为 0
if [ ${#res} -lt 1 ];then
echo "Login Failure"
else
# 取得 IP, 需判断有 Proxy 存在,但是不考虑 Proxy 后是 NAT 情形
IP=${HTTP_X_FORWARDED_FOR:-$REMOTE_ADDR}
FQDN="$LOGIN.$DOMAIN"
# 删除上一次的登入
sql1="delete from RR where USERNAME='$LOGIN'"
# 预设的动态更新项目为 A/MX
sql2="insert into RR(USERNAME,FQDN,TYPE,RDATA) values('$LOGIN','$FQDN','A','$IP')"
sql3="insert into RR(USERNAME,FQDN,TYPE,RDATA) values('$LOGIN','$FQDN','MX','10 $FQDN')"
echo $sql1 | $MYSQL
echo $sql2 | $MYSQL
echo $sql3 | $MYSQL
echo $LOGIN login success @$IP
fi
else
# 以下只是网页的部份,我没有做 DDNS 申请,这个部份我想只要懂网页的朋友应该都会才是
cat <<EOF
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<link rel="stylesheet" href="./style1.css">
</head>
<body>
<BR><BR><center>
<form>
<h3>Abel Dyndns Demo </h3>
Login:<input type=text name=LOGIN ><BR>
Passwd:<input type=password name=PASSWD><BR>
<input type=submit values="Start DynDNS">
</form>
<BR></center>
</body>
</html>
EOF
fi
3.4 dyndns-cron.sh 定时产生 nsupdate
这只程序主要进行读取 Table RR , 并产生 nsupdate 所需要的指令格式后执行 nsupdate, 程序预设
每15秒执行一次(参数如上 dyndns.cfg 中的 UPD_FREQ 更新频率),您可以拿掉 while [ 1 ] 的循环,
改用 crontab 方式来跑,不过这样就较不容易控制一分钟以内的更新频率了,最后,这个程序会把 SOA
的序号改成更新时间,这个时间是 UTC 的秒数(意即 1970/1/1 至今秒数, date +%s 可得),由 SOA 的
序号就可以知道最后的 update 时间,这个原理和 .com 的verisign 或是 dyndns 中的 dyndns.org/
noip.com 是相同的.
另外,根据 RR_VALID 参数,若 USER 的登录时间 小于 现在时间-RR_VALID (秒数),则该 Record 视同
离线,所以我们需要进行 delete 动作
#!/bin/sh
while [ 1 ]
do
# 您必需调整路径,放在 while loop 里是要让修改了设定档即可生效,若不要可放在 while 之外
eval `cat /home/abelyang/dyndns/dyndns.cfg`
cat <<EOF > $CMD_FILE
server $DYNDNS_MASTER
zone $DOMAIN
EOF
# 取得最后一次的更新时间, 多减一秒是为了预防程序的 delay
last=`date -d "-$UPD_FREQ seconds -3 seconds" "+%Y%m%d%H%M%S"`
now=`date "+%Y%m%d%H%M%S"`
# 取得这段时间内有上来更新的 USER,这个部份不检查 IP 不变动情形
# 主要因为 nsupdate 巳执行很快,而且 named 它自己会检查重复更新的东西
echo "select FQDN,TTL,TYPE,RDATA from RR where CREATE_TIME between $last and $now" | $MYSQL| grep -v 'RDATA' | while read FQDN TTL TYPE RDATA RDATA2
do
# 组出更新指令,主要为一个删除,一个增加
echo "update delete $FQDN $TYPE $RDATA $RDATA2" >>$CMD_FILE
echo "update add $FQDN $TTL $TYPE $RDATA $RDATA2" >>$CMD_FILE
done
# 超过 RR_ALIVE (20分钟) 未有 login 数据则清除 DNS 记录
last=`date -d "-$RR_ALIVE seconds" "+%Y%m%d%H%M%S"`
# 备份旧的数据,并清除过时数据 (看你自己要不要备份了)
# echo "insert into RR_LOG select * from RR where CREATE_TIME<$last"|$MYSQL
# echo "delete from RR where CREATE_TIME < $last" |$MYSQL
# 取得过期 (RR_ALIVE) 而未登录的列表进行删除动作,因为我们用了 wildcard (*),所以若别人连时
# 将会被指到 wildcard 所指的 IP 上,而您可这个 Web Server 上做一些文章,例如 Offline 说明等
echo "select USERNAME,FQDN,TYPE,RDATA from RR where CREATE_TIME - $last < 0 order by USERNAME" | $MYSQL | grep -v 'USERNAME' | while read USERNAME FQDN TYPE RDATA RDATA2
do
echo "; delete $FQDN $TYPE $RDATA $RDATA2" >>$CMD_FILE
echo "update delete $FQDN $TYPE $RDATA $RDATA2" >>$CMD_FILE
done
# 自定更新 SOA, 主要是为了让序号字段为现在时间 (UTC)
echo "update delete $DOMAIN SOA" >>$CMD_FILE
echo "update add $DOMAIN 600 SOA ns1.dyndns.twnic.tw abelyang.eai1.twnic.tw $(date +%s) 900 60 604800 60" >>$CMD_FILE
echo "send" >>$CMD_FILE
# 执行 nsupdate 指令
nsupdate $CMD_FILE
# echo "process ok"
sleep $UPD_FREQ
done
3.5 登入及更新方法
所有的东西都准备好了后,我们就可以测试:
wget "http://eai1.twnic.tw/dyndns.cgi?LOGIN=abelyang&PASSWD=abelyang-dyndns" -O /tmp/dyndns-login-status 2>/dev/null
在最多等待15秒(我的默认值)的情况下,就可以更新到 DNS 中了
3.6 其它数据
其它数据如 named.conf , dyndns.twnic.tw zone file 您都可以在前面的说明里找到,我于下面 link
放了一份所有的数据供大家参考,较不用费事 copy & paste ,但不保证下面 link 永远有效 (其中的
.tgz 即有所有档案的 tarball)
http://eai1.twnic.tw/example/
4. DDNS 再探讨
如前言所言, DDNS 可以使用数据库来用 (意即我的范例中可以少掉 dyndns-cron.sh 那只),不过数据库
因其先天的状况,更据我的测试(PowerDNS),在 5 万资 Record 的情况下,只能到达每秒 1000 次的查询,
而且此时尚不考虑同时有 update/delete/insert 等情形,主要因为受限于先天 DB 的 select 速度所致
,当然您可以透过微调或细部处理让这个数字变成1500 或 2000, 但都永不如 BIND 随便都可以透过每秒
6000 次查询,当然用 DB 直接来做一定是可以且更简单的,不过安全性及抗压性 PowerDNS 是随时都会有
当掉的风险,至于用 BIND 倒是没有看过,主要是因为这种 Server 肯定是不递归(recursion no). 所以
著名的 DDNS 厂商都是用 BIND 而不用 DB 方式,因其抗压性不足而致风险过高.
此外,若我们看 dyndns.org/noip.com 的做法,可以知道他们也是用 BIND 来做,你可以查询其 SOA 的序
号即可以知道他每60秒更新一次,若是使用 DB 来做是没有必要顾虑序号问题的 (DB 有 DB 同步方法,用
SOA 序号无关),此外您更可以查看 .com 的 Verisign,他们的做法也是像 BIND 一样,而其以每15秒更新
频率在进行,所以若您使用 .com 的域名,变更DNS 大概只要15秒就可以同步到所有的 .com NameServer,
而不是过去的2天 (因为过去是 AXFR,现在是 IXFR),虽然Verigisn 仍不降低 NS 记录的 TTL 值 (二天),
但至少不会发生像过去最多会4天 .com 的 DNS 数据 Cache 才会过期的情况 (二天的更新频率+二天的
快取时间)
# 检查 .com 的 NameServer (d.gtld-servers.net) SOA 信息来验证
[root@eai1 example]# for i in `seq 1 1000`;do dig +short @d.gtld-servers.net com soa;sleep 1;done
a.gtld-servers.net. nstld.verisign-grs.com. 1153990708 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990708 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990708 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900 # 这里变更了, serial 即时间
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990723 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990738 1800 900 604800 900 # 变更序号
a.gtld-servers.net. nstld.verisign-grs.com. 1153990738 1800 900 604800 900
a.gtld-servers.net. nstld.verisign-grs.com. 1153990738 1800 900 604800 900
5. 结语
我所写的 script 都是以简单的角度来出发,以供大家参考,至于用户及域名管理这个有待想要用的人自行
开发,用 shell script 有利于多数人阅读及了解原理,细节的东西唯有您自己做了后才更能体会.
对多数的公司来说使用 DDNS 是没有意义的,除了 Registy (.com/cn/tw/jp/hk...),或是以 DDNS 做为营
运的公司,而 DDNS其实是不难的,但是网络上较缺乏这方面的介绍文章,所以在此为大家介绍一下这些东西
的细节, 以利想要研究的朋友能初窥门径. 有任何意见都非常欢迎大家多多交流
注:
此外,有些做 DDNS 的公司可能对 IXFR 不了解,而是把所有的 zone type 都设成了 MASTER,然后对这些
NameServer进行 nsupdate , 这种做法也是可以的,不过中间若漏了一步或那一台少做了一件事,那两边
的数据就会不一致,导致可能同一个名称会有不同的解析结果 (例如 gnway.net 做法,我猜测),而像 dyndns.org
/noip.com 和花生壳(vicp.net,oray.net) 等的做法是一样的(也就是和本文所提的做法一样). 而有些
公司则使用 PowerDNS/Mydnl..等套接 DB 的 DNS ,虽然可用,而且方式更简单,但是这些 DDNS 服务肯定
无法负荷大量的查询,因为每次的 dns 查询会在其内产生 N 次的 Select 指令,数据库处理 select 的
速度肯定是比不上 dns flooding 的速度