| 1 | Exercise2 : enable Kerberos logins to a host |
|---|
| 2 | ============================================ |
|---|
| 3 | |
|---|
| 4 | This is to connect a server to an existing Kerberos/LDAP infrastructure. In |
|---|
| 5 | part 1 we'll just enable Kerberos authentication, and in part 2 we'll enable |
|---|
| 6 | LDAP authorization for uid/gid mapping. |
|---|
| 7 | |
|---|
| 8 | Part 1: Kerberos authentication |
|---|
| 9 | =============================== |
|---|
| 10 | |
|---|
| 11 | Your machine must already be working as a Kerberos client (i.e. |
|---|
| 12 | `/etc/krb5.conf` is setup correctly) |
|---|
| 13 | |
|---|
| 14 | Sync your clock |
|---|
| 15 | --------------- |
|---|
| 16 | |
|---|
| 17 | Kerberos only works if your clocks are in close sync (certainly within 5 |
|---|
| 18 | minutes). You can do a one-off clock sync like this: |
|---|
| 19 | |
|---|
| 20 | # ntpdate ntp.ubuntu.com |
|---|
| 21 | |
|---|
| 22 | But it's better to install the ntp daemon, which will continuously keep your |
|---|
| 23 | clock in accurate sync. |
|---|
| 24 | |
|---|
| 25 | # apt-get install ntp |
|---|
| 26 | |
|---|
| 27 | Enable kerberos for sshd |
|---|
| 28 | ------------------------ |
|---|
| 29 | |
|---|
| 30 | In the `sshd_config` file, uncomment the `GSSAPIAuthentication` line and |
|---|
| 31 | set it to `yes`; also add `GSSAPIKeyExchange yes`. Then restart sshd. |
|---|
| 32 | |
|---|
| 33 | # editor /etc/ssh/sshd_config |
|---|
| 34 | ... |
|---|
| 35 | # GSSAPI options |
|---|
| 36 | GSSAPIAuthentication yes |
|---|
| 37 | GSSAPIKeyExchange yes |
|---|
| 38 | .... |
|---|
| 39 | |
|---|
| 40 | # service ssh restart |
|---|
| 41 | |
|---|
| 42 | You're also going to add some extra lines to the end of krb5.conf, because |
|---|
| 43 | of a current limitation in the kadmin utility. |
|---|
| 44 | |
|---|
| 45 | # editor /etc/krb5.conf |
|---|
| 46 | ... |
|---|
| 47 | |
|---|
| 48 | [realms] |
|---|
| 49 | WS.NSRC.ORG = { |
|---|
| 50 | admin_server = kdc1.ws.nsrc.org |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | Now you need to set up a shared key between the KDC and the host's keytab. |
|---|
| 54 | Call over an instructor to do this for you (because we're not letting you |
|---|
| 55 | have admin access to the workshop Kerberos server :-) Here's what they will |
|---|
| 56 | do: |
|---|
| 57 | |
|---|
| 58 | # kadmin -p nsrc/admin |
|---|
| 59 | ... enter secret instructor password |
|---|
| 60 | addprinc -randkey host/pcN.ws.nsrc.org |
|---|
| 61 | ktadd host/pcN.ws.nsrc.org |
|---|
| 62 | ^D |
|---|
| 63 | |
|---|
| 64 | This has (1) created the principal on the KDC, and (2) has copied the key |
|---|
| 65 | into a local keytab file. |
|---|
| 66 | |
|---|
| 67 | You can examine your own keytab using either `klist -k` for a summary, or |
|---|
| 68 | `ktutil` for more detailled information. Inside `ktutil` use '?' for help |
|---|
| 69 | and ^D (ctrl-D) to exit. |
|---|
| 70 | |
|---|
| 71 | # ktutil |
|---|
| 72 | rkt /etc/krb5.keytab |
|---|
| 73 | list -e |
|---|
| 74 | ^D |
|---|
| 75 | |
|---|
| 76 | (The key will be listed multiple times, for use with different encryption |
|---|
| 77 | algorithms) |
|---|
| 78 | |
|---|
| 79 | Now you're going to allow ssh logins for 'testuser'. Because we don't have |
|---|
| 80 | LDAP configured yet, we'll have to create a local account - but there's no |
|---|
| 81 | need to set a password. |
|---|
| 82 | |
|---|
| 83 | # useradd -m -s /bin/bash testuser |
|---|
| 84 | |
|---|
| 85 | Now you're ready to test it. You can try logging in from your own machine to |
|---|
| 86 | yourself, and you can get someone else to login to your machine. |
|---|
| 87 | |
|---|
| 88 | $ kinit testuser # use password from exercise 1 |
|---|
| 89 | $ ssh testuser@pcN.ws.nsrc.org |
|---|
| 90 | |
|---|
| 91 | If instead of logging straight in you see a password prompt from ssh, then |
|---|
| 92 | there's a problem which needs investigating. |
|---|
| 93 | |
|---|
| 94 | Debugging |
|---|
| 95 | --------- |
|---|
| 96 | |
|---|
| 97 | The first things to check are: |
|---|
| 98 | |
|---|
| 99 | * Is your system clock at the correct time? |
|---|
| 100 | * Does your host have working forward and reverse DNS? |
|---|
| 101 | * Did you get a ticket? (klist) |
|---|
| 102 | * Did you restart sshd after setting `GSSAPIAuthentication yes`? |
|---|
| 103 | |
|---|
| 104 | If those are correct, then in another window you can start a new instance of |
|---|
| 105 | sshd in debug mode on a different port: |
|---|
| 106 | |
|---|
| 107 | # /usr/sbin/sshd -d -p99 |
|---|
| 108 | |
|---|
| 109 | Then try to connect to it: |
|---|
| 110 | |
|---|
| 111 | $ ssh -v -p99 testuser@pcN.ws.nsrc.org |
|---|
| 112 | |
|---|
| 113 | You will see logs at both the client and server side. |
|---|
| 114 | |
|---|
| 115 | --------------------------------------------------------------------------- |
|---|
| 116 | |
|---|
| 117 | Part 2: LDAP authorization |
|---|
| 118 | ========================== |
|---|
| 119 | |
|---|
| 120 | This centralises your user/uid/gid/homedir management, and removes the need |
|---|
| 121 | to add local users. |
|---|
| 122 | |
|---|
| 123 | We're going to configure it manually. In practice you'd probably just make a |
|---|
| 124 | tarball containing all the preconfigured files and drop them onto each |
|---|
| 125 | server which needed it. |
|---|
| 126 | |
|---|
| 127 | Install LDAP utils |
|---|
| 128 | ------------------ |
|---|
| 129 | |
|---|
| 130 | # apt-get install ldap-utils libsasl2-modules-gssapi-mit |
|---|
| 131 | |
|---|
| 132 | # editor /etc/ldap/ldap.conf |
|---|
| 133 | BASE dc=ws,dc=nsrc,dc=org |
|---|
| 134 | URI ldap://ldap.ws.nsrc.org |
|---|
| 135 | |
|---|
| 136 | Now this is configured, you should be able to query the LDAP directory - but |
|---|
| 137 | the server is set up only to allow read access if you have a Kerberos ticket. |
|---|
| 138 | |
|---|
| 139 | $ kinit testuser |
|---|
| 140 | $ ldapsearch |
|---|
| 141 | ... should list everything in ldap |
|---|
| 142 | $ ldapsearch "(cn=*test*)" |
|---|
| 143 | ... should list only entries matching the search query |
|---|
| 144 | |
|---|
| 145 | Automated Kerberos ticket |
|---|
| 146 | ------------------------- |
|---|
| 147 | |
|---|
| 148 | For security, the LDAP server only permits connections which are Kerberos |
|---|
| 149 | authenticated and encrypted. This means that the host itself needs a |
|---|
| 150 | Kerberos ticket when doing LDAP lookups. (We could instead have used TLS |
|---|
| 151 | security, but that would involve setting up a Certificate Authority, and we |
|---|
| 152 | may as well leverage our Kerberos setup) |
|---|
| 153 | |
|---|
| 154 | We will run a cronjob every hour, using our existing keytab entry to |
|---|
| 155 | obtain a ticket for `host/pcN.ws.nsrc.org` |
|---|
| 156 | |
|---|
| 157 | # editor /etc/cron.hourly/kerberos |
|---|
| 158 | #!/bin/sh |
|---|
| 159 | /usr/bin/kinit -k host/`hostname` -c /tmp/krb5cc_host |
|---|
| 160 | |
|---|
| 161 | Make it executable, and then run it once manually: |
|---|
| 162 | |
|---|
| 163 | # chmod +x /etc/cron.hourly/kerberos |
|---|
| 164 | # /etc/cron.hourly/kerberos |
|---|
| 165 | |
|---|
| 166 | You can use this keytab to be able to do 'ldapsearch' when logged in as |
|---|
| 167 | root: |
|---|
| 168 | |
|---|
| 169 | # KRB5CCNAME=/tmp/krb5cc_host ldapsearch |
|---|
| 170 | |
|---|
| 171 | Note: our LDAP queries will come from the caching daemon (nscd) which runs |
|---|
| 172 | as root, and so this is all we need. If you wanted to run nscd as a |
|---|
| 173 | different user, you would have to extend the cron script to make the |
|---|
| 174 | ticket readable to that user. e.g. |
|---|
| 175 | |
|---|
| 176 | #!/bin/sh |
|---|
| 177 | /usr/bin/kinit -k host/`hostname` -c /tmp/krb5cc_host |
|---|
| 178 | |
|---|
| 179 | umask 077 |
|---|
| 180 | cp /tmp/krb5cc_host /tmp/krb5cc_nscd |
|---|
| 181 | chown nscd /tmp/krb5cc_nscd |
|---|
| 182 | |
|---|
| 183 | Install nss_ldap |
|---|
| 184 | ---------------- |
|---|
| 185 | |
|---|
| 186 | This is the library which intercepts password/group lookups and redirects |
|---|
| 187 | them to LDAP. |
|---|
| 188 | |
|---|
| 189 | # apt-get install libnss-ldap nscd |
|---|
| 190 | |
|---|
| 191 | (Beware: there is an alternative package `libnss-ldapd` with a trailing "d". |
|---|
| 192 | These exercises have been tested using `libnss-ldap`) |
|---|
| 193 | |
|---|
| 194 | Answer prompted questions as: |
|---|
| 195 | |
|---|
| 196 | LDAP server [ldap://ldap.ws.nsrc.org] |
|---|
| 197 | Distinguished name of search base [dc=ws,dc=nsrc,dc=org] |
|---|
| 198 | LDAP version to use [3] |
|---|
| 199 | Make local root database admin [No] |
|---|
| 200 | Does the LDAP database require login? [No] |
|---|
| 201 | |
|---|
| 202 | NOTE: The LDAP server starts with ldap:// not ldapi:// ! |
|---|
| 203 | |
|---|
| 204 | The configuration file is `/etc/ldap.conf`. We're going to replace it with |
|---|
| 205 | a simple one which uses Kerberos authentication: |
|---|
| 206 | |
|---|
| 207 | # mv /etc/ldap.conf /etc/ldap.conf.example |
|---|
| 208 | # editor /etc/ldap.conf |
|---|
| 209 | krb5_ccname /tmp/krb5cc_host |
|---|
| 210 | use_sasl on |
|---|
| 211 | rootuse_sasl on |
|---|
| 212 | base dc=ws,dc=nsrc,dc=org |
|---|
| 213 | uri ldap://ldap.ws.nsrc.org |
|---|
| 214 | ldap_version 3 |
|---|
| 215 | sasl_secprops minssf=56 |
|---|
| 216 | nss_initgroups_ignoreusers backup,bin,bind,daemon,games,gnats,irc,libuuid,list,lp,mail,man,news,nslcd,ntp,openldap,proxy,root,sshd,sync,sys,syslog,uucp,www-data |
|---|
| 217 | |
|---|
| 218 | We are also going to tweak `nscd.conf` to reduce caching of group |
|---|
| 219 | information from 3600 to 600 seconds. |
|---|
| 220 | |
|---|
| 221 | # editor /etc/nscd.conf |
|---|
| 222 | ... |
|---|
| 223 | positive-time-to-live group 600 |
|---|
| 224 | ... |
|---|
| 225 | |
|---|
| 226 | Configure nsswitch |
|---|
| 227 | ------------------ |
|---|
| 228 | |
|---|
| 229 | This is the point where we actually start to use LDAP for lookups. |
|---|
| 230 | |
|---|
| 231 | # editor /etc/nsswitch.conf |
|---|
| 232 | ... |
|---|
| 233 | passwd: compat ldap |
|---|
| 234 | group: compat ldap |
|---|
| 235 | shadow: compat ldap |
|---|
| 236 | ... |
|---|
| 237 | |
|---|
| 238 | # service nscd restart |
|---|
| 239 | |
|---|
| 240 | At this point you're ready to test: you should be able to map a username |
|---|
| 241 | to a uid over LDAP, even though it doesn't exist in your local |
|---|
| 242 | `/etc/passwd` file |
|---|
| 243 | |
|---|
| 244 | # id ldapuser |
|---|
| 245 | uid=10004(ldapuser) gid=100(users) groups=100(users) |
|---|
| 246 | |
|---|
| 247 | If it fails, places to look are: |
|---|
| 248 | |
|---|
| 249 | * /var/log/auth.log |
|---|
| 250 | * has root got a kerberos ticket? Use the following commands as root: |
|---|
| 251 | # KRB5CCNAME=/tmp/krb5cc_host klist |
|---|
| 252 | # KRB5CCNAME=/tmp/krb5cc_host ldapsearch |
|---|
| 253 | * after any changes which might fix the problem, remember to restart nscd |
|---|
| 254 | because it has both positive and negative caching |
|---|
| 255 | * try stopping nscd, then try `id ldapuser` as root - there will be no |
|---|
| 256 | caching, so it will make a separate LDAP query for each request. You |
|---|
| 257 | can look at tcpdump, and logs on the LDAP server side. |
|---|
| 258 | * if you control the LDAP server, run it in debug mode: |
|---|
| 259 | |
|---|
| 260 | # /etc/init.d/slapd stop |
|---|
| 261 | # KRB5_KTNAME=/etc/ldap/krb5/krb5.keytab slapd -d 255 -u openldap -g openldap |
|---|
| 262 | |
|---|
| 263 | Home directory creation |
|---|
| 264 | ----------------------- |
|---|
| 265 | |
|---|
| 266 | When a user first logs into a machine, you can create their home directory |
|---|
| 267 | automatically via PAM (Pluggable Authentication Modules). |
|---|
| 268 | |
|---|
| 269 | # editor /etc/pam.d/common-session |
|---|
| 270 | ... |
|---|
| 271 | session required pam_mkhomedir.so umask=0022 skel=/etc/skel/ |
|---|
| 272 | ... |
|---|
| 273 | |
|---|
| 274 | --------------------------------------------------------------------------- |
|---|
| 275 | |
|---|
| 276 | Miscellaneous Notes |
|---|
| 277 | ------------------- |
|---|
| 278 | |
|---|
| 279 | Using kadmin to extract the key on the target host itself is almost always |
|---|
| 280 | the best way to set up the shared host/service key. |
|---|
| 281 | |
|---|
| 282 | If joining a Microsoft Active Directory domain: you will need a third-party |
|---|
| 283 | tool such as css_adkadmin (or it may be possible to use bits from samba). |
|---|
| 284 | This may be a starting point: |
|---|
| 285 | |
|---|
| 286 | kinit Administrator |
|---|
| 287 | css_adkadmin -r AD.NSRC.ORG -s dc1.ad.nsrc.org -q "ank -k -attr description=$HOSTNAME +randkey host/$HOSTNAME" |
|---|
| 288 | css_adkadmin -r AD.NSRC.ORG -s dc1.ad.nsrc.org -q "xst +randkey host/$HOSTNAME" |
|---|
| 289 | |
|---|
| 290 | The alternative is to set a manual password on a host principal and then use |
|---|
| 291 | ktutil to create a keytab with the same password. This is awkward, because |
|---|
| 292 | (1) you need to use the right kvno, and (2) you need to repeat it for each |
|---|
| 293 | encryption type which might be used on your network. |
|---|
| 294 | |
|---|
| 295 | [KDC side] |
|---|
| 296 | kadmin |
|---|
| 297 | addprinc host/pcX.ws.nsrc.org |
|---|
| 298 | ... you are prompted for password |
|---|
| 299 | getprinc host/pcX.ws.nsrc.org |
|---|
| 300 | ... make a note of the kvno |
|---|
| 301 | |
|---|
| 302 | [host side] |
|---|
| 303 | # ktutil |
|---|
| 304 | ktutil: addent -password -p host/pcX.ws.nsrc.org -k 4 -e aes256-cts |
|---|
| 305 | Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: |
|---|
| 306 | ktutil: addent -password -p host/pcX.ws.nsrc.org -k 4 -e arcfour-hmac |
|---|
| 307 | Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: |
|---|
| 308 | ktutil: addent -password -p host/pcX.ws.nsrc.org -k 4 -e des3-hmac-sha1 |
|---|
| 309 | Password for host/pcX.ws.nsrc.org@WS.NSRC.ORG: |
|---|
| 310 | ktutil: list |
|---|
| 311 | slot KVNO Principal |
|---|
| 312 | ---- ---- --------------------------------------------------------------------- |
|---|
| 313 | 1 4 host/pcX.ws.nsrc.org@WS.NSRC.ORG |
|---|
| 314 | 2 4 host/pcX.ws.nsrc.org@WS.NSRC.ORG |
|---|
| 315 | 3 4 host/pcX.ws.nsrc.org@WS.NSRC.ORG |
|---|
| 316 | ktutil: wkt /etc/krb5.keytab |
|---|
| 317 | |
|---|