Linux通过pam实现ssh登录

准备工作搭建CentOS7,地址为:192.168.51.104,192.168.51.105

1.配置pam

# 192.168.51.104 /etc/pam.d/sshd
#%PAM-1.0
auth       sufficient   pam_python.so auth.py #新增内容
auth       required     pam_sepermit.so
auth       substack     password-auth
auth       include      postlogin
# Used with polkit to reauthorize users in remote sessions
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    required     pam_namespace.so
session    optional     pam_keyinit.so force revoke
session    include      password-auth
session    include      postlogin
# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare

2.pam_python.so制作

# 192.168.51.104

yum install pam pam-devel -y   #安装编译需要的依赖
 
wget -O pam-python_1.0.8.tar.gz https://sourceforge.net/projects/pam-python/files/latest/download?source=files --no-check-certificate   #下载pam_python模块

tar xvfpam-python_1.0.8.tar.gz
 
cd pam-python_1.0.8
 
make lib
 
cp  src/build/lib.linux-x86_64-2.7/pam_python.so /usr/lib64/security/

3.编写auth.py

# 192.168.51.104
import syslog
import base64
import sys
import json

try:
    sys.path.append('/usr/local/lib/python2.7/site-packages')
    sys.path.append('/usr/local/lib64/python2.7/site-packages')
except Exception as e:
    raise Exception(str(e))

import requests

EXCLUDE_USER  = ["root"]
# Notice: Auth use 127.0.0.1, requests set header X_FORWARDED_FOR to send real IP
AUTH_URL = 'http://127.0.0.1/auth' # 认证服务地址


def otp_log(msg):
    syslog.openlog(facility=syslog.LOG_AUTH)
    syslog.syslog("otp auth log: "+msg)
    syslog.closelog()


def do_auth(url, username, password, host):
    username = username
    password = password
    headers = {'X-FORWARDED-FOR': host}
    try:
        resp = requests.post(url, json={'username': username, 'password': password}, headers=headers)
    except Exception as e:
        raise Exception(str(e))
    else:
        if resp.status_code == 200:
            return True
        else:
            return False


def pam_sm_authenticate(pamh, flags, argv):
    try:
        user = pamh.get_user(None)
    except pamh.exception as e:
        return e.pam_result
    try:
        if user in EXCLUDE_USER:
            return pamh.PAM_AUTH_ERR
        msg = pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, "Password:")
        resp = pamh.conversation(msg)
        otp_log("[resp] %s" % resp.resp)
        result =  do_auth(AUTH_URL, pamh.user, resp.resp, pamh.rhost)
        otp_log("[result] %s" % result)
        if result:
            return pamh.PAM_SUCCESS
        else:
            return pamh.PAM_AUTH_ERR
    except Exception as e:
        raise Exception(str(e))
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

auth.py添加到pam库

# 192.168.51.104
cp auth.py /usr/lib/security/

4.配置sshd

# 192.168.51.104 /etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

SyslogFacility AUTHPRIV

AuthorizedKeysFile      .ssh/authorized_keys

PasswordAuthentication yes

ChallengeResponseAuthentication no

GSSAPIAuthentication yes
GSSAPICleanupCredentials no

UsePAM yes
X11Forwarding yes

AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS

重新启动sshd服务

# 192.168.51.104
service sshd restart

5.验证

1.安装flask并启动web服务

# 192.168.51.104
pip install flask

2.编写服务端用于验证pam功能

新建pam_server.py

# 192.168.51.104
from flask import Flask, request, Response

app = Flask(__name__)
USERNAME = 'Test'
PASSWORD = 'Password'


@app.route('/auth', methods=['POST', 'GET'])
def auth():
    if request.method == 'POST':
    	print(request.json)
        if request.json.get('username') == USERNAME and request.form.get('password') == PASSWORD:
            return Response(status=200)

    return Response(status=401)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8088, debug=True)

3.执行pam_server.py

# 192.168.51.104
[root@host ~]# python pam_server.py
 * Serving Flask app 'pam_server' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://192.168.51.104:8088/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 849-362-694

4.本机添加用户

# 192.168.51.104
useradd Test

5.ssh登录验证,可以成功登录

# 192.168.51.105
[root@host2 ~]$ ssh Test@192.168.51.104
The authenticity of host '192.168.51.104 (192.168.51.104)' can't be established.
ECDSA key fingerprint is SHA256:c2HeAq0o66TI9MO8AmMK0eZlTc5zvDCud0cBIg6+FGA.
ECDSA key fingerprint is MD5:65:cb:3f:6e:68:59:5c:d4:ad:7a:a2:6e:20:a4:59:46.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.51.104' (ECDSA) to the list of known hosts.
Test@192.168.51.104's password:
Last login: Fri Mar 25 16:13:50 2022 from 192.168.51.106
[Test@host2 ~]$

6.登录成功后查看pam server调试信息

# 192.168.51.104
[root@host ~]# python pam_server.py
 * Serving Flask app 'pam_server' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://192.168.51.105:8088/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 849-362-694
 
{'username': 'Test', 'password': 'Password'}
192.168.51.104 - - [25/Mar/2022 16:55:57] "POST /auth HTTP/1.1" 200 -
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值