1. 程式人生 > >Kerberos+LDAP+NFSv4 實現單點登錄(續2)--一鍵安裝

Kerberos+LDAP+NFSv4 實現單點登錄(續2)--一鍵安裝

ldap

Kerberos+LDAP+NFSv4 實現單點登錄(續2)--一鍵安裝

( 附:LDAP簡單認證登錄 login4ldap-ver0.0.6.zip 源代碼 下載地址 http://u.163.com/NeMVmlIT 提取碼: ObEubL7Y )

上篇Kerberos+LDAP+NFSv4 實現單點登錄(續1)鏈接地址http://lulinlin1.lofter.com/post/1cf3848f_11f58066?act=qbbloglofter_20150506_01

本篇是前兩篇的總結,編寫成一鍵安裝腳本onekeysso.sh,並需名為dns.ldif文件.dns.ldif是從bind9-dyndb-ldap包的模式文件修改而來,可參考上篇

下面是onekeysso.sh的內容,將onekeysso.sh和dns.ldif放在同一目錄下,以root用戶運行onekeysso.sh

說明:腳本會卸載刪除一些包及文件(如要重新一鍵安裝),如果你的系統已是正在用於生產環境,請小心,還是請準備幹凈的系統一鍵安裝

環境:debian 10

運行:
root@debian:~# ls
dns.ldif onekeysso.sh
root@debian:~# ./onekeysso.sh

內容:
#! /bin/bash

echo -n "before install new pack,Shall I remove some old files,database and uninstall [yes/no]?"

read
if [ "$REPLY" = "yes" ]; then
echo "install setup"
else
echo "exit install"
exit 0
fi

/etc/init.d/slapd stop
/etc/init.d/heimdal-kdc stop
apt-get -y remove --purge slapd
apt-get -y remove --purge heimdal-kdc
apt-get -y remove --purge krb5-config
apt-get -y remove --purge bind9-dyndb-ldap bind9 isc-dhcp-server-ldap isc-dhcp-server

rm /etc/ldap/krb5.keytab
rm /etc/bind/krb5.keytab
sed -i ‘/127.0.0.2/d‘ /etc/hosts

echo -n "input net(default: 192.168.1.0):"
read mynet
if [ -z $mynet ]; then
mynet="192.168.1.0"
fi

if [[ $mynet =~ [0-9]+.[0-9]+.[0-9]+.[0] ]] && !([[ $mynet =~ [^0-9.]+ ]]); then
echo ok
else
echo "必須是網絡地址0"
exit 1
fi

IFS=. read -r myp1 myp2 myp3 myp4 <<< $mynet

mybroadcast=echo $mynet | sed ‘s/.0$/.255/‘

myiprange="echo $mynet | sed ‘s/.0$/.20/‘ echo $mynet | sed ‘s/.0$/.240/‘"

echo -n "input static ip(default: "$myp1.$myp2.$myp3".11):"
read mystaticip
if [ -z $mystaticip ]; then
mystaticip=$myp1.$myp2.$myp3.11
fi

if [[ $mystaticip =~ $myp1.$myp2.$myp3.[0-9]+ ]] && !([[ $mystaticip =~ [^0-9.]+ ]]); then
echo ok
else
echo "必須是上面所設的同網段"
exit 1
fi
IFS=. read -r mys1 mys2 mys3 mys4 <<< $mystaticip
if [ $mys4 = 0 ]; then
echo "不能是網絡地址0"
exit 1
fi

if [ $mys4 = 255 ]; then
echo "不能是廣播地址255"
exit 1
fi

echo -n "input router(default: "$myp1.$myp2.$myp3".1):"
read myrouter
if [ -z $myrouter ]; then
myrouter=$myp1.$myp2.$myp3.1
fi

if [[ $myrouter =~ [0-9]+.[0-9]+.[0-9]+.[0-9]+ ]] && !([[ $myrouter =~ [^0-9.]+ ]]); then
echo ok
else
echo error
exit 1
fi

echo -n "input hostname:"
read mykdc
if [[ $mykdc =~ [a-z]+ ]] && !([[ $mykdc =~ [^a-z]+ ]]); then
echo ok
else
echo "僅支持小寫字母"
exit 1
fi

echo -n "input domain:"
read mydomain
if [[ $mydomain =~ [a-z.]+ ]] && !([[ $mydomain =~ [^a-z.]+ ]]); then
echo ok
else
echo "僅支持小寫字母和點號"
exit 1
fi

echo ‘127.0.0.2 ‘$mykdc‘.‘$mydomain‘ ‘$mykdc >> /etc/hosts
echo $mykdc > /etc/hostname
hostname $mykdc

mydomain=hostname -d

myrealm=hostname -d | tr a-z A-Z
mysuffix="dc=echo $mydomain | sed ‘s/^\.//; s/\.$//; s/\./,dc=/g‘"
mybasedn=$mysuffix

myfullname=$mykdc.$mydomain

echo $myfullname
echo $mybasedn
echo $mybroadcast
echo $myiprange

#預配置krb5-config
echo ‘krb5-config krb5-config/default_realm string ‘$myrealm | debconf-set-selections
echo ‘krb5-config krb5-config/admin_server string 127.0.0.1‘ | debconf-set-selections
echo ‘krb5-config krb5-config/kerberos_servers string 127.0.0.1‘ | debconf-set-selections

apt-get -y install schema2ldif gzip
apt-get -y install slapd
apt-get -y install heimdal-kdc
apt-get -y install bind9 bind9-dyndb-ldap isc-dhcp-server isc-dhcp-server-ldap libsasl2-modules-gssapi-heimdal dnsutils

/etc/init.d/slapd stop
/etc/init.d/heimdal-kdc stop
/etc/init.d/bind9 stop
/etc/init.d/isc-dhcp-server stop

#1.修改配置
#1)ldap
#1.1)將krb5用戶主體映射到ldap用戶
sed -i ‘$a olcAuthzRegexp: {0}uid=dns/‘"$mykdc"‘,cn=gssapi,cn=auth krb5PrincipalName=DNS/‘"$mykdc"‘@‘"$myrealm"‘,ou=hdkrb5,‘"$mysuffix"‘‘ /etc/ldap/slapd.d/cn=config.ldif

#1.2)設置LDAP ACL,允許如DNS/[email protected]寫ldap數據庫
sed -i ‘/olcAccess: {2}to * by * read/a olcAccess: {3}to by self write by dn="cn=admin,‘"$mysuffix"‘" write by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by read‘ /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb.ldif
sed -i ‘/olcAccess: {2}to * by * read/a olcAccess: {2}to dn.subtree="ou=dns,‘"$mysuffix"‘" by dn="krb5PrincipalName=DNS/‘"$mykdc"‘@‘"$myrealm"‘,ou=hdkrb5,‘"$mysuffix"‘" write by read‘ /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb.ldif
sed -i ‘/olcAccess: {2}to * by \
read/d‘ /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb.ldif

#1.3)缺省搜索
sed -i ‘$a olcDefaultSearchBase: ‘"$mybasedn"‘‘ /etc/ldap/slapd.d/cn=config/olcDatabase={-1}frontend.ldif

#1.4)必須啟用同步,否則dig查詢被拒絕
sed -i ‘/olcModuleLoad: {0}/a olcModuleLoad: {1}syncprov‘ /etc/ldap/slapd.d/cn=config/cn=module{0}.ldif

slapadd -b cn=config <<-EOF
dn: olcOverlay=syncprov,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov
olcSpNoPresent: TRUE
EOF

chown openldap:openldap /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb
chown openldap:openldap /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb/olcOverlay={0}syncprov.ldif

#2)krb
#2.1)kdc.conf
sed -i ‘/[kdc]/a \n addresses = 0.0.0.0\n‘ /etc/heimdal-kdc/kdc.conf
sed -i ‘/dbname = \/var\/lib\/heimdal-kdc\/heimdal/a \n dbname = ldap:ou=hdkrb5,‘"$mysuffix"‘\n mkey_file = \/var\/lib\/heimdal-kdc\/m-key\n realm = ‘"$myrealm"‘‘ /etc/heimdal-kdc/kdc.conf
sed -i ‘/dbname = \/var\/lib\/heimdal-kdc\/heimdal/d‘ /etc/heimdal-kdc/kdc.conf

#2.2)krb5.conf
sed -i ‘/[libdefaults]/a \n allow_weak_crypto = true\n dns_lookup_kdc = true\n dns_lookup_realm = true‘ /etc/krb5.conf
sed -i ‘/admin_server = 127.0.0.1/d‘ /etc/krb5.conf
sed -i ‘/forwardable = true/d‘ /etc/krb5.conf
sed -i ‘/proxiable = true/d‘ /etc/krb5.conf
sed -i ‘/# default_tgs_enctypes = des3-hmac-sha1/a default_tgs_enctypes = aes256-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5‘ /etc/krb5.conf
sed -i ‘/# default_tkt_enctypes = des3-hmac-sha1/a default_tkt_enctypes = aes256-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5‘ /etc/krb5.conf

#3)dhcp
mysecret=ddns-confgen | grep secret
sed -i ‘/INTERFACESv4=""/a INTERFACESv4="‘"ls /sys/class/net | sed ‘/lo/d‘ | xargs"‘"‘ /etc/default/isc-dhcp-server
sed -i ‘/INTERFACESv4=""/d‘ /etc/default/isc-dhcp-server
sed -i ‘s/^/#/‘ /etc/dhcp/dhcpd.conf
sed -i ‘1a ldap-server "127.0.0.1";\nldap-base-dn "‘"$mybasedn"‘";\nldap-method dynamic;‘ /etc/dhcp/dhcpd.conf
#將原放在ldap的密鑰改放在dhcpd.conf
sed -i ‘1a key "ddns-key" { algorithm hmac-sha256; ‘"$mysecret"‘ }‘ /etc/dhcp/dhcpd.conf
chmod o-r /etc/dhcp/dhcpd.conf

#4)dns
sed -i ‘/include "\/etc\/bind\/named.conf.local";/a include "/etc/bind/named.conf.ldap";‘ /etc/bind/named.conf
sed -i ‘/include "\/etc\/bind\/named.conf.local";/d‘ /etc/bind/named.conf
sed -i ‘/include "\/etc\/bind\/named.conf.default-zones";/d‘ /etc/bind/named.conf
sed -i ‘/directory "\/var\/cache\/bind";/a \n allow-recursion { none; };‘ /etc/bind/named.conf.options
sed -i ‘/dnssec-validation auto;/d‘ /etc/bind/named.conf.options
sed -i ‘/auth-nxdomain no;/d‘ /etc/bind/named.conf.options
sed -i ‘/listen-on-v6 { any; };/d‘ /etc/bind/named.conf.options

#4.1)重裝bind9時,bind用戶及用戶組ID可能有改變,而重裝又沒改到named.run
chown bind:bind /var/cache/bind/named.run

#4.2)新建named.conf.ldap
cat <<-EOF > /etc/bind/named.conf.ldap
logging {
channel default_debug {
file "named.run";
severity debug;
};
};

key "ddns-key" {
algorithm hmac-sha256;
$mysecret
};

controls {
inet 127.0.0.1 allow { 127.0.0.1; } keys { ddns-key; };
};

//不同體系路徑如/usr/lib/i386-linux-gnu/bind/ldap.so
dyndb "my_db_name" "dpkg-query -S ldap.so | grep bind9-dyndb-ldap | sed ‘s/bind9-dyndb-ldap: //‘" {
//bind9-dyndb-ldap有bug,必須加server_id此行
server_id "";
directory "/var/cache/bind";
uri "ldap://127.0.0.1";
base "ou=dns,$mysuffix";

//認證機制
auth_method "sasl";
sasl_mech "GSSAPI";
//--v-- 添加krb5主體
sasl_auth_name "DNS/$mykdc";
krb5_keytab "FILE:/etc/bind/krb5.keytab";
//--^--

//超時及重連接間隔的值需設大一點,解決因使用SASL認證無法寫問題
timeout 50;
reconnect_interval 100;
};
EOF
chmod o-r /etc/bind/named.conf.ldap

#2.添加模式
#1)krb
schema2ldif /etc/ldap/schema/hdb.schema | slapadd -b cn=config

#2)dhcp
zcat /usr/share/doc/isc-dhcp-server-ldap/dhcp.schema.gz | schema2ldif -c dhcp | slapadd -b cn=config

#3)dns
slapadd -b cn=config -l dns.ldif

chown openldap:openldap /etc/ldap/slapd.d/cn=config/cn=schema/cn={}hdb.ldif
chown openldap:openldap /etc/ldap/slapd.d/cn=config/cn=schema/cn={
}dhcp.ldif
chown openldap:openldap /etc/ldap/slapd.d/cn=config/cn=schema/cn={*}dns.ldif

#3.添加條目
slapadd -b $mysuffix <<-EOF
#1)
dn: ou=hdkrb5,$mysuffix
krb5PrincipalName: default@$myrealm
ou: hdkrb5
objectClass: krb5Principal
objectClass: organizationalUnit

dn: ou=users,ou=hdkrb5,$mysuffix
objectClass: organizationalUnit
ou: users

dn: ou=hosts,ou=hdkrb5,$mysuffix
objectClass: organizationalUnit
ou: hosts

dn: ou=groups,$mysuffix
objectClass: organizationalUnit
ou: groups

dn: ou=sudoers,$mysuffix
objectClass: organizationalUnit
ou: sudoers

dn: ou=roles,$mysuffix
objectClass: organizationalUnit
ou: roles

#2)dhcp
dn: cn=$mykdc,$mysuffix
objectClass: dhcpServer
cn: $mykdc
dhcpServiceDN: cn=dhcp,$mysuffix

#Here is the config tree
dn: cn=dhcp,$mysuffix
cn: dhcp
objectClass: dhcpService
dhcpPrimaryDN: cn=$mykdc,$mysuffix
dhcpStatements: ddns-update-style interim
dhcpStatements: ignore client-updates
#動態更新DNS的密鑰改放到dhcpd.conf,方便設置訪問權限控制,免泄漏密鑰
#dhcpStatements: key "ddns-key" { algorithm hmac-sha256; $mysecret }
dhcpStatements: zone $mydomain { primary 127.0.0.1; key ddns-key; }
dhcpStatements: default-lease-time 600
dhcpStatements: max-lease-time 7200

#Set up a subnet declaration with a pool statement. Also note that we have a dhcpOptions object with this entry
dn: cn=$mynet,cn=dhcp,$mysuffix
cn: $mynet
objectClass: dhcpSubnet
objectClass: dhcpOptions
dhcpOption: domain-name "$mydomain"
dhcpOption: domain-name-servers $mystaticip
dhcpOption: routers $myrouter
dhcpOption: subnet-mask 255.255.255.0
dhcpOption: broadcast-address $mybroadcast
dhcpNetMask: 24
dhcpRange: $myiprange

#3)dns
#定義正、反向區域存儲到ldap數據庫
dn: ou=dns,$mysuffix
objectClass: organizationalUnit
ou: dns

#Zone
dn: idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsZone
objectClass: idnsRecord
idnsName: $mydomain
#動態更新
idnsAllowDynUpdate: TRUE
#同步反向解析
idnsAllowSyncPTR: TRUE
#動態更新策略
idnsUpdatePolicy: grant ddns-key zonesub ANY;
idnsZoneActive: TRUE
idnsSOAmName: $mykdc
idnsSOArName: root.$mykdc
idnsSOAserial: 1
idnsSOArefresh: 10800
idnsSOAretry: 900
idnsSOAexpire: 604800
idnsSOAminimum: 86400
#域名服務器記錄
NSRecord: $mydomain.
ARecord: $mystaticip

#別名
dn: idnsName=$mykdc,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: $mykdc
CNAMERecord: $mydomain.

#DNS records for zone
#--v-- SRV資源記錄
dn: idnsName=_kerberos._udp,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: _kerberos._udp
SRVRecord: 0 100 88 $mykdc

dn: idnsName=_kerberos._tcp,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: _kerberos._tcp
SRVRecord: 0 100 88 $mykdc

dn: idnsName=_kpasswd._udp,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: _kpasswd._udp
SRVRecord: 0 100 464 $mykdc

dn: idnsName=_ldap._tcp,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: _ldap._tcp
SRVRecord: 0 100 389 $mykdc

dn: idnsName=_ntp._udp,idnsName=$mydomain,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: _ntp._udp
SRVRecord: 0 100 123 $mykdc
#--^--

#--v-- 反向解析
dn: idnsName=$myp3.$myp2.$myp1.in-addr.arpa,ou=dns,$mysuffix
objectClass: idnsZone
objectClass: idnsRecord
idnsName: $myp3.$myp2.$myp1.in-addr.arpa
idnsAllowDynUpdate: TRUE
idnsUpdatePolicy: grant ddns-key zonesub ANY;
idnsZoneActive: TRUE
idnsSOAmName: $myfullname.
idnsSOArName: root.$myfullname.
idnsSOAserial: 1
idnsSOArefresh: 10800
idnsSOAretry: 900
idnsSOAexpire: 604800
idnsSOAminimum: 86400
NSRecord: $myfullname.

#必須配置kdc服務器地址的反向解析
dn: idnsName=$mys4,idnsName=$myp3.$myp2.$myp1.in-addr.arpa,ou=dns,$mysuffix
objectClass: idnsRecord
idnsName: $mys4
PTRRecord: $myfullname.
#--^--
EOF

#4.其它
/etc/init.d/slapd start
/etc/init.d/heimdal-kdc start

#1)初始化krb
kadmin -l init --realm-max-ticket-life=unlimited --realm-max-renewable-life=unlimited $myrealm

#2)添加krb5主體
#2.1)
kadmin -l add -r --use-defaults ldap/$mykdc

#使ldap/mykdc成為應用服務器
kadmin -l modify -a -disallow-svr ldap/$mykdc

#導出keytab
kadmin -l ext -k /etc/ldap/krb5.keytab ldap/$mykdc

#不知為何在/etc/default/slapd指定KRB5_KTNAME沒作用,因此還是復制一份到/etc/下
cp -a /etc/ldap/krb5.keytab /etc/krb5.keytab

#krb5.keytab擁有者改為openldap,並只openldap用戶可讀
chown openldap:openldap /etc/ldap/krb5.keytab
chmod o-r /etc/ldap/krb5.keytab
chmod g-r /etc/ldap/krb5.keytab

#在/etc/default/slapd裏增加一行
sed -i ‘$a export KRB5_KTNAME=/etc/ldap/krb5.keytab‘ /etc/default/slapd

#2.2)
kadmin -l add -r --use-defaults DNS/$mykdc
kadmin -l ext -k /etc/bind/krb5.keytab DNS/$mykdc

#krb5.keytab擁有者改為bind,並只bind用戶可讀
chown bind:bind /etc/bind/krb5.keytab
chmod o-r /etc/bind/krb5.keytab
chmod g-r /etc/bind/krb5.keytab

#3)略
#ssl
#密碼同步

#4)
sed -i ‘/127.0.0.2/d‘ /etc/hosts
sed -i ‘/iface eth0 inet dhcp/a iface eth0 inet static\naddress ‘"$mystaticip"‘\nnetmask 255.255.255.0‘ /etc/network/interfaces
sed -i ‘/iface eth0 inet dhcp/d‘ /etc/network/interfaces
#/etc/init.d/networking restart
/etc/init.d/bind9 start
/etc/init.d/isc-dhcp-server start

後記:
1.dig查詢DNS被拒絕問題
bind9-dyndb-ldap文檔有提到SyncRepl (RFC 4533) ,但沒說明LDAP必須啟用同步.
起初腳本沒啟用LDAP同步,DNS解析總被拒絕,調試bind9提示SyncRepl (RFC 4533)有問題,啟用了LDAP同步就正常.
因此腳本添加加了啟用LDAP同步.

2.krb5Key屬性安全問題
腳本沒設置krb5Key屬性的讀寫權限,因此是匿名可讀,heimdal文檔也沒說明krb5Key屬性的安全問題.
為提高安全性,用戶可自行參考userPassword屬性的設置方法來禁止匿名讀取krb5Key屬性.

3.動態更新DNS模式
一般手冊推薦標準模式standard,但使用了bind9-dyndb-ldap,在模式standard下客戶機第一次分配地址能添加到DNS,但客戶機地址改變時無法更新DNS,提示沒DHCIDRecord屬性,而bind-dyndb-ldap模式沒有DHCIDRecord屬性.
所以動態更新DNS模式改為interim,客戶機地址改變時已可正常更新DNS

Kerberos+LDAP+NFSv4 實現單點登錄(續2)--一鍵安裝