Centos7:OpenVPN+GoogleAuth+企业微信

根据等保要求,要符合双因子认证要求,密码+证书,密码过于简单一成不变也不行,结合googleauth模块可解决上述问题,OTP多种随机数生成规则,我选用基于时间的OTP,基于企业微信完成对用户访问的限制,测试与生产使用2套密钥。

  1. openvpn配置
script-security 3    #认证过程将用户提交的用户名及密码保存在系统变量中
reneg-sec 0  #不进行密码过期检查
auth-user-pass-verify /etc/openvpn/checkpwd.py via-env  #认证脚本,这里需要注意via-env与via-file  ,都说via-env不安全,还是要根据接受程度来吧。
username-as-common-name  #把用户名当作通用凭证

2 . 企业微信开启API调用并读取用户进入应用消息通知,这里我用的django
1).django建模

class gjskvpnuser(models.Model):
    '''VPN用户列表'''
    username = models.CharField('用户名', max_length=200)
    userslat = models.CharField('加盐值', max_length=200)
    otpcode = models.IntegerField('动态码')
    otptype = models.CharField('环境类型', max_length=200)
    realname = models.CharField('真实姓名', max_length=200)
    status = models.CharField('状态', max_length=200)

2).django views.py

from django.http import HttpResponse
from wechatpy.enterprise.crypto import WeChatCrypto
from wechatpy.exceptions import InvalidSignatureException
from wechatpy.enterprise.exceptions import InvalidCorpIdException
from wechatpy.enterprise import parse_message, create_reply
import time
import pyotp
import pymysql
from .models import vpnuser
import re

def index(request):
    if(request.method == 'POST'):
        signature=request.GET.get('msg_signature')
        timestamp=request.GET.get('timestamp')
        echo_str=request.GET.get('echostr')
        nonce=request.GET.get('nonce')
        crypto = WeChatCrypto("xxxx", "yyyy", "zzzz")
        raw_message = request.body
#######解密用户请求
        decrypted_xml = crypto.decrypt_message(
            raw_message,
            signature,
            timestamp,
            nonce
        )

        msg = parse_message(decrypted_xml)
######获取用户进入应用事件是哪个标签,0生产、1测试
        parte = re.match(r'^.*#sendmsg#_(\d{1})#', str(msg))
        sourceuser = msg.source
        reqtype = parte.group(1)
        obj = vpnuser.objects.filter(username=sourceuser, otptype=reqtype).values('userslat')
        print(obj)
        usersalt = obj[0].get('userslat')
        charp = pyotp.TOTP(usersalt, interval=300)
        otpcode = charp.now()
        if int(reqtype) == 0:
            rtype="生产"
        else:
            rtype="测试"
        rmsg="""您的{0}环境在动态密码为:{1}\n有效期5分钟。""".format(rtype, otpcode)
########回复用户
    xml = create_reply(rmsg).render()
    encrypted_xml = crypto.encrypt_message(xml, nonce, timestamp)

    return HttpResponse(encrypted_xml)

  1. openvpn服务器端checkpwd.py结合mysql对用户身份进行OTP认证,脚本获取传入的系统变量
#!/usr/bin/python
import pymysql
import sys
import os
import pyotp

db_cmd="`which mysql`"
db_host="127.0.0.1"
db_user="dbuser"
db_pass="dbpass"
db_name="dbname"

conn = pymysql.connect(
    host=db_host,
    user=db_user,
    password=db_pass,
    database=db_name,
    charset="utf8",
    cursorclass=pymysql.cursors.DictCursor)

cursor = conn.cursor()
sql_cmd = """select userslat from otp_vpnuser where username='{0}' and otptype='0'""".format(os.environ['username'])
if cursor.execute(sql_cmd):
    re_list = cursor.fetchall()[0]
    if re_list.get('userslat'):
        authotp = pyotp.TOTP(re_list.get('userslat'), interval=300)
        if authotp.verify(os.environ['password']):
            sys.exit(0)
        else:
            sys.exit(1)
    else:
        sys.exit(1)
else:
    sys.exit(1)

conn.close()
  1. openvpn客户端设置,因为动态密码缘故,过期难免要重启服务自动填充密码
    1).密码文件,设置权限600
auth-user-pass /etc/openvpn/.passwd.txt

2).auto_pass.py密码自动更新文件,并加入定时任务。

#!/usr/bin/env python
import socket
import pyotp
import os

slatcode = "xxxxxx" #用户标识码为固定的,不用去数据库读取
hostname = socket.gethostname()
with open(r"/etc/openvpn/.passwd.txt", 'w') as f:
    o_otp = pyotp.TOTP(slatcode, interval=300)
    f.write(hostname + '\n')
    f.write(o_otp.now())

scode = os.system("ping 172.16.0.1 -c 1 -W 1 -q")
if scode != 0:
    os.system("systemctl restart openvpn@client")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • 本文主要参考的博客文章链接 https://www.fandenggui.com/post/centos7-ins...
    super_pcm阅读 8,499评论 3 3
  • CentOS 7 安装文档 说明 开头的行表示注释 开头的行表示需要在 mysql 中执行 $ 开头的行表示需要执...
    apple524阅读 588评论 0 1
  • 关于jumpserver的安装 这段时间没事做、看了一下有关职位的技能需求的信息,就有了今天的测试。 环境cent...
    Al_不期而遇阅读 1,656评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,518评论 16 22
  • 创业是很多人的梦想,多少人为了理想和不甘选择了创业来实现自我价值,我就是其中一个。 创业后,我由女人变成了超人,什...
    亦宝宝阅读 1,805评论 4 1