Linux: 通过pam_python实现ssh双因子认证测试记录_七侠镇莫尛貝_20190730

参考资料:http://www.ipcpu.com/2016/04/linux-pam-python/

测试环境:ubuntu16.04 srv

测试步骤:

1.从https://github.com/ipcpu/pam-python-ipcpu  下载pam_python源代码。

2.服务端安装gcc:  参考:https://blog.csdn.net/lucifa_li/article/details/79483686

apt-get  install  build-essential

3.安装pam_python依赖库:

apt install libpam0g-dev

pam_python依赖python2.7,如果没有还要装python2.7

4.添加测试用户:useradd_test.sh

#!/bin/bash

USERNAME=test
#USERNAME=$1

USERPASSWORD=userpassword
MOBNUM=18818181818


#删除用户,连带删除/home/username目录
userdel -r $USERNAME
sleep 1

useradd $USERNAME 
#passwd $USERNAME 
#修改用户密码
echo $USERNAME:$USERPASSWORD|chpasswd

usermod -s /bin/bash $USERNAME 
mkdir /home/$USERNAME
chown $USERNAME:$USERNAME /home/$USERNAME
usermod -d /home/$USERNAME $USERNAME
usermod -c ',,'$MOBNUM',' $USERNAME

echo -e 用户名:口令:用户标识号:组标识号:注释性描述:用户主目录:命令解释程序
cat /etc/passwd |grep $USERNAME

5.编译:

    make lib

编译成功后,把生成的pam_python.so(这里有编译好的二进制版本,仅在ubuntu16下测试过,就不用安装上面安装编译环境和依赖库了)放到/lib/x86_64-linux-gnu/security/下 (文章说放到/lib64/security/下,实测不行。可能是操作系统差异。)

 把测试的auth.py放到/lib64/security/下 (在pam-python-ipcpu-master\pam-python-ipcpu-master\utils\2factor-with-PIN\下)

这里做了一下修改,增加/var/log/pam_python_auth.log日志输出,以解决docker版ubuntu16下没有syslog的问题:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
import random, string, hashlib, requests
import pwd, syslog
import logging
logging.basicConfig(level=logging.DEBUG,#控制台打印的日志级别
                    filename='/var/log/pam_python_auth.log',
                    filemode='a',##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
                    #a是追加模式,默认如果不写的话,就是追加模式
                    format=
                    '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                    #日志格式
                    )

def auth_log(msg):
	"""Send errors to default auth log"""
        '''	syslog.openlog(facility=syslog.LOG_AUTH)'''
	syslog.syslog("IPCPU-PAM-AUTH: " + msg)
	syslog.closelog()
	logging.info("PAM_PYTHON-AUTH: " + msg)


def get_user_number(user):
	"""Extract user's phone number for pw entry"""
	try:
		comments = pwd.getpwnam(user).pw_gecos
	except KeyError: # Bad user name
		auth_log("No local user (%s) found." % user)
		return -1
	
	try:
		return comments.split(',')[2] # Return Office Phone
	except IndexError: # Bad comment section format
		auth_log("Invalid comment block for user %s. Phone number must be listed as Office Phone" % (user))
		return -1
		
	
def pam_sm_authenticate(pamh, flags, argv):
	try:
		user = pamh.get_user()
		user_number = get_user_number(user)
	except pamh.exception, e:
		return e.pam_result
	
	if user is None or user_number == -1:
		msg = pamh.Message(pamh.PAM_ERROR_MSG, "Unable to send one time PIN.\nPlease contact your System Administrator")
		pamh.conversation(msg)
		return pamh.PAM_AUTH_ERR
		###""return pamh.PAM_ABORT""
		
		
	for attempt in range(0,3): # 3 attempts to enter the one time PIN
		msg = pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, "Enter Your PIN: ")
		resp = pamh.conversation(msg)

		if resp.resp == user_number:
			auth_log("user: " + user + " login successful with PIN:" + resp.resp)
			return pamh.PAM_SUCCESS
		else:
			auth_log("user: " + user + " login failed with PIN:" + resp.resp)
			continue
	return pamh.PAM_AUTH_ERR

def pam_sm_setcred(pamh, flags, argv):
	return pamh.PAM_SUCCESS

def pam_sm_acct_mgmt(pamh, flags, argv):
	return pamh.PAM_SUCCESS

def pam_sm_open_session(pamh, flags, argv):
	return pamh.PAM_SUCCESS

def pam_sm_close_session(pamh, flags, argv):
	return pamh.PAM_SUCCESS

def pam_sm_chauthtok(pamh, flags, argv):
	return pamh.PAM_SUCCESS

这个.py实现了读取/etc/passwd文件的用户手机号(存放位置 test:x:1000:1000:,,18818181818,:/home/test:/bin/bash),写syslog(/var/log/syslog ,验证手机号等功能)

 

如果ldd pam_python.so 发现缺少库,可以到网上找解决办法。

我后面用docker版ubuntu16测试时,发现还依赖一个libpython2.7.so.1.0,(我在docker下使用的是自制的一个python2.7绿色版,未带libpython2.7.so.1.0这个文件),放置在/usr/lib/x86_64-linux-gnu/目录下即可。

 

6.修改/etc/pam.d/sshd,在文件最上增加一行(在最上加,将来ssh登陆测试时就先出现验证PIN码提示,再提示输入服务器用户密码;在最下加,就先提示输入服务器用户密码再出现验证PIN码提示):

    auth    requisite   pam_python.so auth.py

修改/etc/ssh/sshd_config,确保:

    ChallengeResponseAuthentication yes

    UsePAM yes。

7.重启ssh服务:

    systemctl restart sshd.service

    或者

    service ssh restart

8.测试:在另外一台服务器上,ssh test@IP,提示先输入PIN,再输入test账号口令。

 

 

20190730补充:

附录:一键安装pam_python测试环境脚本

#!/bin/bash

PAM_SSHD_FILE=/etc/pam.d/sshd
SSHD_CONFIG=/etc/ssh/sshd_config
PAM_SSHD_2P_CONTENT=$(sed -n 2p $PAM_SSHD_FILE)
#echo $PAM_SSHD_2P_CONTENT

PAM_SSHD_CONF="auth      requisite    pam_python.so   auth_pwd.py"

basepath=$(cd `dirname $0`; pwd)
#echo 当前目录:$basepath

if [ ! -d "/lib64/security" ]; then
	mkdir /lib64/security
fi
#rm -fr /lib64/security
rm -fr /lib64/security/auth_pwd.py
ln -s $basepath/lib64_security/auth_pwd.py /lib64/security/

rm -fr /lib/x86_64-linux-gnu/security/pam_python.so
#cp  $basepath/lib_x86_64-linux-gnu_security/pam_python.so /lib/x86_64-linux-gnu/security/
ln -s  $basepath/lib_x86_64-linux-gnu_security/pam_python.so /lib/x86_64-linux-gnu/security/

rm -fr /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
ln -s $basepath/usr_lib_x86_64-linux-gnu/libpython2.7.so.1.0 /usr/lib/x86_64-linux-gnu/ 

rm -fr /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
ln -s $basepath/usr_lib_x86_64-linux-gnu/libpython2.7.so.1.0 /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0

cd $basepath/python27x64_green
./init_python_env.sh

#modify /etc/pam.d/sshd for pam_python config
#在/etc/pam.d/sshd 第二行增加pam_python配置
cd $basepath
if [ "$PAM_SSHD_2P_CONTENT" != "$PAM_SSHD_CONF" ];then
	sed -i '2 i\'"$PAM_SSHD_CONF" $PAM_SSHD_FILE 
	echo -e "修改sshd 增加pam_python配置 OK!"
else
	echo -e "sshd中pam_pthon 配置已经存在,略过!"
fi

#modify /etc/ssh/sshd_config for pam_python
#LINE_NUM=grep -n "UsePAM" /etc/ssh/sshd_config|cut -d ":" -f 1
#ChallengeResponseAuthentication no
##UsePAM yes
#删除关键字开头的某行
#sed -i '/^ChallengeResponseAuthentication/d' $SSHD_CONFIG 
sed -i 's/ChallengeResponseAuthentication/#ChallengeResponseAuthentication/g' $SSHD_CONFIG 
sed -i '$a\ChallengeResponseAuthentication yes' $SSHD_CONFIG 
sed -i '$a\UsePAM yes' $SSHD_CONFIG 

echo -e "pam_python for Ubuntu16 env OK!"

#restart sshd
cd $basepath
./restart_sshd.sh

#add test user: test/userpassword
./useradd_test.sh

#ALL OK!
echo -e "Now run: ssh test@ip for test!"

20190801补充:

在auth.py基础上做了一些修改,实现了ssh登录时的二维码扫码登陆(显示二维码用qrcode_terminal库。二维码验证使用了公司的一个多因子认证产品的二维码接口和移动端APP)。可以方便地根据用户名做判断,比如:如果是root用户,就无需扫码直接登陆,其他用户则必须扫码登陆,防止使用secureCRT等客户端登陆时把自己拦在服务器外。

 

使用短信、APP动态口令登陆待补充。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值