Samba 4 已經釋出很長一段時間了 因此趁著升級電腦與 centos 6 順便將 Samba 3 AD DC + dhcpd + bind 更新為 Samba 4 + bind 9 dlz 模組 + dhcpd
DC DQDN名稱 : samba4dc
DC IP : 192.168.0.1/24
- 首先到 https://portal.enterprisesamba.com/users/sign_up 註冊. 方便使用 yum 升級 samba , 如果使用 source 安裝就不需申請. 登入後把給 centos6 用的 sernet-samba-4.1.repo 檔下載回來並修改檔案中 USERNAME:ACCESSKEY 的部分.
- 升級前先備份 /etc/samba, /var/lib/samba, /etc/dhcp, /etc/named.conf, /var/named, /var/cache/samba 等目錄
- 安裝 samba 4
# yum install sernet-samba -y
- 升級 Samba AD 網域
移動設定檔mv /etc/smb.conf /etc/smb.PDC.conf
將舊資料庫等檔案移到其他位置
# mv /var/lib/samba/ /var/lib/samba.PDC/ # mv /var/cache/samba/ /var/cache/samba.PDC/
新增資料夾. 並將升級時會用到的資料庫檔案複製到該目錄
# mkdir /var/lib/samba.PDC/dbdir/ # cp -p /var/lib/samba.PDC/private/secrets.tdb /var/lib/samba.PDC/dbdir/ # cp -p /var/lib/samba.PDC/private/schannel_store.tdb /var/lib/samba.PDC/dbdir/ # cp -p /var/lib/samba.PDC/private/passdb.tdb /var/lib/samba.PDC/dbdir/ # cp -p /var/cache/samba.PDC/gencache_notrans.tdb /var/lib/samba.PDC/dbdir/ # cp -p /var/cache/samba.PDC/group_mapping.tdb /var/lib/samba.PDC/dbdir/ # cp -p /var/cache/samba.PDC/account_policy.tdb /var/lib/samba.PDC/dbdir/
升級資料庫以及使用 bind_dlz 模組
# samba-tool domain classicupgrade --dbdir=/var/lib/samba.PDC/dbdir/ --use-xattrs=yes --realm=home.com --dns-backend=BIND9_DLZ /etc/smb.PDC.conf --option="interfaces=lo eth0" --option="bind interfaces only=yes"
PS: --option="interfaces=lo eth0" --option="bind interfaces only=yes" 這是限定 samba 只作用在網卡 loopback 及 eth0
- 調整產生的 samba 設定即啟動檔
/etc/samba/smb.conf[global] workgroup = HOME realm = home.com netbios name = SAMBA4DC interfaces = lo, eth0 bind interfaces only = Yes server role = active directory domain controller server services = s3fs, rpc, nbt, wrepl, ldap, cldap, kdc, drepl, winbind, ntp_signd, kcc, dnsupdate idmap_ldb:use rfc2307 = yes log level = 2 log file = /var/log/samba/log.%m max log size = 50 wins support = yes syslog = 0 username map = /etc/samba/smbusers domain master = yes domain logons = yes local master = yes preferred master = yes [netlogon] path = /var/lib/samba/sysvol/home.com/scripts read only = No [sysvol] path = /var/lib/samba/sysvol read only = No [homes] comment = Home Directories browseable = no read only = No valid users = %S create mask = 0700 directory mask = 0700 [nas] comment = storage path = /home/data public = yes writable = yes printable = no write list = +adm
因為是作為 dc , 只要開啟 sernet-samba-ad 服務. 其餘 sernet-samba-nmbd, sernet-samba-smbd, sernet-samba-winbindd 不須啟動.
# chkconfig --level 2345 sernet-samba-ad on
- 調整 bind9 & kerberos 設定
/etc/named.confoptions { listen-on port 53 { 127.0.0.1; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; forwarders { 168.95.1.1; }; forward first; listen-on { home; }; allow-recursion {home;}; allow-update { home; }; allow-query { home; }; allow-transfer { home;}; listen-on-v6 { none; }; tkey-gssapi-keytab "/var/lib/samba/private/dns.keytab"; #加入這行 auth-nxdomain yes; empty-zones-enable no; version none; hostname none; server-id none; }; logging { channel Named_log { file "data/named.run";# versions 5 size 5m; severity dynamic; print-severity yes; print-time yes; }; category default {Named_log; }; category xfer-out {Named_log; }; category queries {Named_log; }; }; acl "home" { 192.168.0.0/24; 127.0.0.1;}; controls { inet 127.0.0.1 allow { localhost; } keys { rndc-key; }; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; include "/etc/rndc.key"; include "/var/lib/samba/private/named.conf"; #加入這行
/var/lib/samba/private/named.conf
lz "AD DNS Zone" { # For BIND 9.8.0 database "dlopen /usr/lib64/samba/bind9/dlz_bind9.so"; #選擇對應的 bind 版本 # For BIND 9.9.0 # database "dlopen /usr/lib64/samba/bind9/dlz_bind9_9.so"; };
修改 keytab 檔案權限讓 bind 可以用其來動態更新 zone
# chgrp named /var/lib/samba/private # chgrp named /var/lib/samba/private/dns.keytab # chmod g+r /var/lib/samba/private/dns.keytab
連結 kerberos 設定檔到 /etc 下
# ln -sf /var/lib/samba/private/krb5.conf /etc/krb5.conf
重啟 named
# service named restart
增加反解析區域
# samba-tool dns zonecreate samba4dc.home.com 0.168.192.in-addr.arpa
將 DC 的 PTR 加入反解區域
# samba-tool dns add samba4dc.home.com 0.168.192.in-addr.arpa 1 PTR samba4dc.home.com
如果有設定 ntpd (選擇性) 請修改 socket 的位址讓 samba 可以讀取
driftfile /var/lib/ntp/drift logfile /var/log/ntp ntpsigndsocket /var/lib/samba/ntp_signd restrict default kod nomodify notrap nopeer mssntp noquery restrict -6 default kod nomodify notrap nopeer noquery restrict 127.0.0.1 restrict -6 ::1 restrict 192.168.0.0 mask 255.255.255.0 nomodify notrap server 0.centos.pool.ntp.org iburst server 1.centos.pool.ntp.org iburst server 2.centos.pool.ntp.org iburst server 3.centos.pool.ntp.org iburst includefile /etc/ntp/crypto/pw keys /etc/ntp/keys
修改權限及重啟 ntpd
# chown root:ntp /var/lib/
samba/ntp_ signd # chmod 750 /var/lib/ samba/ntp_ signd # service ntpd restart 重啟 samba
# service smbd stop # service nmbd stop # service sernet-samba-ad start
- DHCPD 設定
在 AD 裡新增 dhcp 這個使用者並給予權限讓它可以動態更新 DNS(也可以使用 Windows 遠端伺服器管理工具 RSAT 來新增)# samba-tool user create dhcp --description="Unprivileged user for DNS updates via DHCP server" # samba-tool group addmembers DnsAdmins dhcp
將該使用者憑證匯出成 keytab 檔
# cd /etc/dhcp # samba-tool domain exportkeytab --principal=dhcp@HOME.COM dhcpd.keytab # chown root:dhcpd /etc/dhcp/dhcpd.keytab # chmod 440 /etc/dhcp/dhcpd.keytab # chgrp dhcpd /etc/dhcp
新增以下兩個執行檔
/usr/local/sbin/dhcp-dyndns.sh#!/bin/bash $(dirname $0)/dns-krbnsupdate.sh $@ 2>&1 | logger &
/usr/local/sbin/dns-krbnsupdate.sh
#!/bin/bash # This script is for secure DDNS updates using GSS/TSIG # Version: 0.1 ## CONFIGURATION ## # Kerberos realm realm="HOME.COM" # Kerberos principal principal="dhcp@$realm" # Kerberos keytab keytab="/etc/dhcp/dhcpd.keytab" # Kerberos credentials cache krb5cc="/tmp/krb5cc_0" # Use MIT kerberos args instead of heimdal. KRB5MIT="YES" # Domain appended to hostname domain="home.com" # Space separated list of DNS servers for sending updates to NSRVS="cchisheng.home.com" # Default DNS resource records TTL RRTTL="3600" # Do not use TXT RRs (rfc4701) NOTXTRRS="YES" # Additional nsupdate flags (-g already applied), e.g. "-d" for debug #NSUPDFLAGS="-d" # Run in the foreground (for manual run only!!!), it's better to use "-d" as script's first argument #DEBUG="YES" ###################################################### ## VARIABLES ## [ "$1" = "-d" ] && DEBUG="YES" && shift action=$1 ip=$2 DHCID=$3 name=${4%%.*} [ -n "$5" ] && RRTTL="$5" _usage() { echo "Usage:" echo " `basename $0` [-d] add ip-address dhcid|mac-address hostname [dns-ttl]" echo " `basename $0` [-d] delete ip-address dhcid|mac-address" } _kerberos() { export KRB5_KTNAME="$keytab" export KRB5CCNAME="$krb5cc" if [ "$KRB5MIT" = "YES" ]; then KLISTARG="-s" else KLISTARG="-t" fi klist $KLISTARG || kinit -k -t "$keytab" -c "$krb5cc" "$principal" || { echo "DDNS: kinit failed"; exit 1; } } _main() { umask 77 if [ -z "$ip" ] || [ -z "$DHCID" ]; then _usage exit 1 fi ## NSUPDATE ## case "$action" in add) RRPTR="$name.$domain" if [ "$NOTXTRRS" != "YES" ]; then NOTXTRRS="" RRAOLD=`host $RRPTR | awk '/has address/ {print $4}'` if [ -n "$RRAOLD" ]; then RRTXTOLD=`host -t txt "$RRPTR" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'` [ -z "$RRTXTOLD" ] && echo "DDNS: adding records for $ip ($RRPTR) FAILED: has A record but no DHCID, not mine" && exit 1 RRTXT=`echo "$DHCID$RRPTR" | sha256sum` RRTXT="000101${RRTXT%% *}" [ "$RRTXT" != "$RRTXTOLD" ] && echo "DDNS: adding records for $ip ($RRPTR) FAILED: has A record but DHCID is wrong" && exit 1 else RRTXT=`echo "$DHCID$RRPTR" | sha256sum` RRTXT="000101${RRTXT%% *}" fi else NOTXTRRS=";" fi RRPTRNAME=`echo $ip | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'` _kerberos for NSRV in $NSRVS; do nsupdate -g $NSUPDFLAGS << UPDATE server $NSRV realm $realm update delete $RRPTR. $RRTTL A ${NOTXTRRS}update delete $RRPTR. $RRTTL TXT ${NOTXTRRS}update add $RRPTR. $RRTTL TXT $RRTXT update add $RRPTR. $RRTTL A $ip send update delete $RRPTRNAME. $RRTTL PTR update add $RRPTRNAME. $RRTTL PTR $name.$domain. send UPDATE result=$? [ "$result" -eq "0" ] && echo "DDNS: adding records for $ip ($RRPTR) succeeded" && exit 0 done [ "$result" != "0" ] && echo "DDNS: adding records for $ip ($RRPTR) FAILED: nsupdate status $result" && exit "$result" ;; delete) RRPTR=`host $ip | awk '/domain name pointer/ { sub(/\.$/, "", $5); print $5}'` if [ "$NOTXTRRS" != "YES" ]; then NOTXTRRS="" if [ -n "$RRPTR" ]; then RRTXTOLD=`host -t txt "$RRPTR" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'` [ -z "$RRTXTOLD" ] && echo "DDNS: removing records for $ip ($RRPTR) FAILED: has A record but no DHCID, not mine" && exit 1 RRTXT=`echo "$DHCID$RRPTR" | sha256sum` RRTXT="000101${RRTXT%% *}" [ "$RRTXT" != "$RRTXTOLD" ] && echo "DDNS: removing records for $ip ($RRPTR) FAILED: has A record but DHCID is wrong" && exit 1 else echo "DDNS: removing records for $ip FAILED: has no PTR, can not determine A record" && exit 1 fi else NOTXTRRS=";" fi RRPTRNAME=`echo $ip | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'` _kerberos for NSRV in $NSRVS; do nsupdate -g $NSUPDFLAGS << UPDATE server $NSRV realm $realm update delete $RRPTR. $RRTTL A ${NOTXTRRS}update delete $RRPTR. $RRTTL TXT send update delete $RRPTRNAME. $RRTTL PTR send UPDATE result=$? [ "$result" -eq "0" ] && echo "DDNS: removing records for $ip ($RRPTR) succeeded" && exit 0 done [ "$result" != "0" ] && echo "DDNS: removing records for $ip ($RRPTR) FAILED: nsupdate status $result" && exit "$result" ;; *) _usage && exit 1 ;; esac } if [ "$DEBUG" = "YES" ]; then _main else : _main | logger -s -t dhcpd & fi
修改 /etc/dhcp/dhcpd.conf
subnet 192.168.0.0 netmask 255.255.255.0 { authoritative; option netbios-name-servers 192.168.0.1; option domain-name-servers 192.168.0.1; option domain-name "home.com"; option netbios-node-type 8; option routers 192.168.1.1; option subnet-mask 255.255.255.0; default-lease-time 259200; range 192.168.0.10 192.168.1.250; on commit { set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientName = pick-first-value(option host-name, host-decl-name); set ClientDHCID = binary-to-ascii(16, 8, ":", hardware); execute("/usr/local/sbin/dhcp-dyndns.sh", "add", ClientIP, ClientDHCID, ClientName); } on release { set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientName = pick-first-value(option host-name, host-decl-name); set ClientDHCID = binary-to-ascii(16, 8, ":", hardware); execute("/usr/local/sbin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID); } on expiry { set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientName = pick-first-value(option host-name, host-decl-name); set ClientDHCID = binary-to-ascii(16, 8, ":", hardware); execute("/usr/local/sbin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID); } }
改變檔案權限
# chmod 755 /usr/local/sbin/dhcp-dyndns.sh # chmod 755 /usr/local/sbin/dns-krbnsupdate.sh
重啟 dhcpd
# service dhcpd restart
- 測試
# samba_dnsupdate --verbose --all-names
若上述指令沒有錯誤表示 bind9 設定正確. 若有錯誤請檢查檔案及目錄權限, 讓 bind9 可以讀取 dns.keytab
當 dhcp client 端開機或者在 Windows 命令提示視窗執行 ipconfig /renew 時, server上的 syslog 會有以下紀錄, 表示動態更新成功Dec 9 00:00:15 samba4dc dhcpd: DDNS: adding records for 192.168.0.186 (win7.home.com) succeeded Dec 9 00:00:15 samba4dc logger: dhcpd: DDNS: adding records for 192.168.0.186 (win7.home.com) succeeded
- 問題
I.Windows client本身會執行 secure dns update, 因此 named 紀錄裡會有更新失敗的錯誤. 由於我們是透過dhcpd更新dns, 因此該錯誤可以忽略.
II.Samba4目前對於讓 dc 及file server 在同台伺服器上尚未完整支援, 因此 client 端在網路芳鄰內找不到 server, 需要手動輸入 \\server 連結伺服器. 如果在登入指令檔或者 RSAT 的使用者管理裡指定連線磁碟機就可以解決該問題
III. RSAT 的 DNS 管理員可以新增刪除紀錄但有時會有錯誤訊息但不影響 - 參考文獻
https://wiki.samba.org/index.php/User_Documentation
http://blog.michael.kuron-germany.de/2011/02/isc-dhcpd-dynamic-dns-updates-against-secure-microsoft-dns/
https://wiki.archlinux.org/index.php/Samba_4_Active_Directory_Domain_Controller