Kerberos+LDAP+NFSv4 实现单点登陆(续2)--一键安装linux
( 附: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_01api
本篇是前两篇的总结,编写成一键安装脚本onekeysso.sh,并需名为dns.ldif文件.dns.ldif是从bind9-dyndb-ldap包的模式文件修改而来,可参考上篇安全
下面是onekeysso.sh的内容,将onekeysso.sh和dns.ldif放在同一目录下,以root用户运行onekeysso.shbash
重要提示:本脚本用在全新的安装,不是原步平滑升级配置.脚本会完全卸载删除一些包及原有文件(如krb5主密钥、krb5/ldap数据库等等),并从新初始化为空的数据库文件.若是你的系统已经是正在用于生产环境,请当心,请备份你的数据文件,本脚本会清空你一切的数据库.仍是请准备干净(未用在生产环境)的系统一键安装服务器
环境:debian 10网络
运行:
root@debian:~# ls
dns.ldif onekeysso.sh
root@debian:~# ./onekeysso.shfrontend
内容:dom
#! /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/mykdc@XX.YY写ldap数据库 sed -i '/olcAccess: {2}to \* by \* read/a olcAccess: {3}to * 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同步.tcp
2.krb5Key属性安全问题
脚本没设置krb5Key属性的读写权限,所以是匿名可读,heimdal文档也没说明krb5Key属性的安全问题.
为提升安全性,用户可自行参考userPassword属性的设置方法来禁止匿名读取krb5Key属性.
3.动态更新DNS模式
通常手册推荐标准模式standard,但使用了bind9-dyndb-ldap,在模式standard下客户机第一次分配地址能添加到DNS,但客户机地址改变时没法更新DNS,提示没DHCIDRecord属性,而bind-dyndb-ldap模式没有DHCIDRecord属性.
因此动态更新DNS模式改成interim,客户机地址改变时已可正常更新DNS
修正:
#1.2)设置LDAP ACL
的{3}to * by self write by
改成{3}to * by