标签:ssh key authorizedkeyscommand mysql linux
使用数据库统一管理ssh登陆用户密钥信息
需求是由一个开发部门提出的,他们需要在他们的测试服务器上开放root权限给所有的开发人员,同时要给每个开发人员配置无密码登录,由于使用ssh默认的认证文件存储公钥不方便人员信息的管理(例如一个人离职后不方便在大量的key中找到他的key,且需要在大量的服务器上全部删除)。
基于上述需求,我们决定将所有人员的key和其对应的fingerprint保存在数据库中,而且每个fingerprint都对应一个真实用户名,在用户登录的时候,虽然都是使用root用户登录,但是,其登录的时候不会再到autherized_keys文件中查找key,而是根据用户传递的fingerprint去数据库中查找对应的公钥。
为了实现上述的需求,我们需要用户在使用ssh登录的时候首先去执行一个取公钥的脚本,然后再根据脚本取回的key来验证用户。这里需要用到两个ssh的配置参数AuthorizedKeysCommand和AuthorizedKeysCommandUser,第一个参数用来指定登录时执行的脚本文件,第二个参数用来指定这个脚本的用户,这里要注意,这个脚本权限必须是700且属组属主必须是root。这两个配置参数在低版本的openssh中无法使用,需要首先升级openssh的版本,而且在升级时需要我们修改一部分openssh的源码,本文中升级到了ssh 6.6p1这个版本。
一、升级openssh
准备升级openssh的源码包,在官网上找到6.6版本的源码包并下载:
[root@localhost ~]# wget http://ftp.jaist.ac.jp/pub/OpenBSD/OpenSSH/portable/openssh-6.6p1.tar.gz [root@localhost ~]# tar -zxf openssh-6.6p1.tar.gz -C /usr/src/ [root@localhost ~]# cd /usr/src/openssh-6.6p1
解包完成后,我们要更改一下其源码,更改解压后目录下的auth2-pubkey.c文件
//512行左右 struct passwd *pw; struct stat st; int status, devnull, p[2], i; pid_t pid; //char *username, errmsg[512]; 注释掉此行代码 char *username, *fp, errmsg[512]; 添加此行代码 if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != ‘/‘) return 0; //552行左右 if (pipe(p) != 0) { error("%s: pipe: %s", __func__, strerror(errno)); goto out; } // debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"", 注释掉这行 // options.authorized_keys_command, user_pw->pw_name, pw->pw_name); 注释掉这行 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 添加这行 debug3("Running AuthorizedKeysCommand: \"%s %s %s\" as \"%s\"", options.authorized_keys_command, user_pw->pw_name, fp, pw->pw_name); /* * Don‘t want to call this in the child, where it can fatal() and * run cleanup_exit() code. */ restore_uid(); switch ((pid = fork())) { case -1: /* error */ //602行左右 /* stdin is pointed to /dev/null at this point */ if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { error("%s: dup2: %s", __func__, strerror(errno)); _exit(1); } execl(options.authorized_keys_command, // options.authorized_keys_command, user_pw->pw_name, NULL); 注释掉此行 options.authorized_keys_command, user_pw->pw_name, fp, NULL); 添加此行 error("AuthorizedKeysCommand %s exec failed: %s", options.authorized_keys_command, strerror(errno)); _exit(127); default: /* parent */ break; } free(fp); 添加此行 temporarily_use_uid(pw);
改完上述源码后,我们将更改后的源码打成rpm包来升级:
[root@localhost ~]# cd /usr/src/openssh-6.6p1/contrib/redhat #本文系统为CentOS 6.5 [root@localhost ~]# vim openssh.spec #更改spec文档,关闭一些用不到的参数 # Do we want to disable building of x11-askpass? (1=yes 0=no) %define no_x11_askpass 1 #此处设置为1,不构建x11-askpass # Do we want to disable building of gnome-askpass? (1=yes 0=no) %define no_gnome_askpass 1 #此处设置为1,不构建gnome-askpass
[root@localhost ~]# cd /usr/src/ [root@localhost ~]# tar -zcf openssh-6.6p1.tar.gz openssh-6.6p1/ 注意:此处必须在/usr/src/目录下打包,否则制作rpm包时会报错,且文件名必须如上所示 [root@localhost ~]# cd /usr/src/openssh-6.6p1/contrib/redhat [root@localhost ~]# rpmbuild -bb openssh.spec #开始制作rpm包 注意:制作rpm包的时候可能会遇到依赖包不全的问题,常见的有pam pam-devel glibc glibc-devel tcp_wrappers-devel openssl098e gcc等,此处不再一一赘述。
打包完成后,在/usr/src/redhat/RPMS/x86_64目录下有打好的rpm包。用rpm方式升级安装。我在安装的时候遇到了版本冲突的问题,然后直接强制安装。
安装完成后,修改/etc/ssh/sshd_config配置文件:
#AuthorizedKeysFile .ssh/authorized_keys //注释掉这一行 #AuthorizedPrincipalsFile none AuthorizedKeysCommand /bin/ssh-zhy.sh //添加这一行,指定查找ssh-key的脚本 AuthorizedKeysCommandUser root //添加这一行,指定运行脚本的用户,必须是root
AuthorizedKeysCommand回向ssh-key脚本传递两个位置参数,$1是登陆用户名,$2是登陆用户的fingerprint,在脚本中可以直接用$2来获取fingerprint。
准备取ssh-key的脚本,该脚本可以是shell脚本,也可以是其他脚本,只要能从数据库中取到对应的key就可以了,此处我使用的是shell脚本。数据库中保存各用户的key和fingerprint,根据fingerprint来取对应的key值,这样就保证所有用户即使都使用root登陆,也可以根据其fingerprint值来对应查找到对应的登陆人员从而完成人员记录。
准备好脚本后,放到配置文件中配置的位置,改脚本文件属主和属组为root,脚本权限为700,这两步是必须设置的。配置完成后准备好存储key的数据库,然后重启sshd服务。此时再登陆的时候就会去数据库中查找key信息,如果在数据库中找不到对应的key,依然会去authorized_keys文件中找。
配置好后,我们只需要通过管理数据库,就可以很方便的管理所有人的key。也可以方便后期的管理界面的开发。
本文出自 “手艺人” 博客,请务必保留此出处http://8838848.blog.51cto.com/8828848/1697188
标签:ssh key authorizedkeyscommand mysql linux
原文地址:http://8838848.blog.51cto.com/8828848/1697188