avatar

瓜生花子八宝粥

少壮不努力 老了看浏览器

  • 首页
  • 开源项目
  • Linux
  • Windows
  • Docker
  • 中间件
  • 数据库
主页 OpenVPN Access Server 绑定用户MAC地址
文章

OpenVPN Access Server 绑定用户MAC地址

发表于 2024-12-1 更新于 2025-01- 8
作者 jepwei
52~67 分钟 阅读

获取脚本

wget https://swupdate.openvpn.net/scripts/post_auth_mac_address_checking.py -O /root/mac.py

脚本内容如下

# OpenVPN Access Server MAC address checking post_auth script.
# Johan Draaisma
#
# This script can be used with LOCAL, PAM, LDAP, and RADIUS authentication.
# It adds an additional check when authentication is done through the VPN connection.
# It applies to all 3 connection profiles types (server-locked, user-locked, auto-login).
# Windows, Linux, and macOS will be reporting MAC addresses. However, Android and iOS
# devices will not, due to technical reasons. They will instead by reporting UUID. For
# simplicity and legacy reasons we will just call it MAC address from here on in, but
# it can be in theory any unique hardware-based string that the client reports to us.
#
# Please note: RADIUS/LDAP case insensitivity may lead to the system recognizing
# Billy.Bob and billy.bob as 2 separate accounts, when using RADIUS/LDAP.
#
#
# Full documentation and explanation can be found here:
# https://openvpn.net/vpn-server-resources/access-server-post-auth-script-host-checking/
#
# Script last updated in January 2020


import re

from pyovpn.plugin import *

# Optionally set this string to a known public IP address (such as the
# public IP address of machines connecting from a trusted location, such
# as the corporate LAN). If set, all users must do the first login from this
# IP address, so the machine's hardware (MAC/UUID) address can be recorded.
#
# If this is empty, which it is by default, then registrations for the first
# MAC address for a user account will be done automatically on first login.
#
# If this is set to "NONE" or "DISABLED" then the server administrator must
# always manually register each MAC/UUID address by hand on the command line.
# For that, we refer you to our documentation.
first_login_ip_addr = ""

# If False or undefined, AS will call us asynchronously in a worker thread.
# If True, AS will call us synchronously (server will block during call),
# however we can assume asynchronous behavior by returning a Twisted
# Deferred object.
SYNCHRONOUS=False

# this function is called by the Access Server after normal VPN or web authentication
def post_auth(authcred, attributes, authret, info):
    print("********** POST_AUTH %s %s %s %s" % (authcred, attributes, authret, info))

    # get user's property list, or create it if absent
    proplist = authret.setdefault('proplist', {})

    # user properties to save - we will use this to pass the hw_addr_save property to be
    # saved in the user property database.
    proplist_save = {}

    error = ""

    # If a VPN client authentication attempt is made, do these steps:
    # Check if there is a known MAC address for this client
    # If not, register it
    # If yes, check it
    #
    # An additional optional requirement is that first time registration must occur
    # from a specific IP address, as specified in the first_login_ip_addr set above
    #
    # The 'error' text goes to the VPN client and is shown to the user.
    # The 'print' lines go to the log file at /var/log/openvpnas.log (by default).

    if attributes.get('vpn_auth'):                  # only do this for VPN authentication
        hw_addr = authcred.get('client_hw_addr')    # MAC address reported by the VPN client
        username = authcred.get('username')         # User name of the VPN client login attempt
        clientip = authcred.get('client_ip_addr')   # IP address of VPN client login attempt
        if hw_addr:
            hw_addr_save = proplist.get('pvt_hw_addr')           # saved MAC address
            hw_addr_save2 = proplist.get('pvt_hw_addr2')         # saved MAC address (secondary)
            if hw_addr_save:
                if not hw_addr == hw_addr_save and not hw_addr == hw_addr_save2:
                    error = "The hardware MAC/UUID address reported by this VPN client does not match the registered address."
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    if hw_addr_save2:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s or %s"  % (hw_addr_save, hw_addr_save2))
                    else:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s" % hw_addr_save)
                    print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")
                else:
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    if hw_addr_save2:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s or %s" % (hw_addr_save, hw_addr_save2))
                    else:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s" % hw_addr_save)
                    print("***** POST_AUTH MAC CHECK: connection attempt        : SUCCESS")

            else:
                # First login by this user, save MAC addr.
                if not first_login_ip_addr or first_login_ip_addr == clientip:
                    proplist_save['pvt_hw_addr'] = hw_addr
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    print("***** POST_AUTH MAC CHECK: action taken              : MAC address learned and locked.")
                    print("***** POST_AUTH MAC CHECK: connection attempt        : SUCCESS")
                else:
                    error = "Your attempt to login from an address not approved for MAC/UUID address registration has been denied."
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: action taken              : attempt to register client MAC/UUID address from restricted address denied.")
                    print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")

        else:
            error = "VPN client is not reporting a MAC/UUID address. Please verify that a suitable OpenVPN client is being used."
            print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
            print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
            print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : NONE REPORTED")
            print("***** POST_AUTH MAC CHECK: action taken              : VPN connection denied with a suitable error message.")
            print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")

    # process error, if one occurred
    if error:
        authret['status'] = FAIL
        authret['reason'] = error          # this error string is written to the server log file
        authret['client_reason'] = error   # this error string is reported to the client user

    return authret, proplist_save

加载脚本到OpenVPN-AS

cd /usr/local/openvpn_as/scripts
./sacli --key "auth.module.post_auth_script" --value_file=/root/mac.py ConfigPut
./sacli start

取消加载命令如下:

cd /usr/local/openvpn_as/scripts
./sacli --key "auth.module.post_auth_script" ConfigDel
./sacli start

重启OpenVPN服务

systemctl restart openvpnas

MAC的添加与重置


#定位客户端设备的mac地址方法有两个
#1.让客户自己查自己设备的mac地址
#2.通过/var/log/openvpn.log观察对方的mac地址(client MAC/UUID address)

#添加硬件辅助地址的方法(最多两个),以exampleuser用户为例
cd /usr/local/openvpn_as/scripts
./sacli --user "exampleuser" --key "pvt_hw_addr2" --value "ef:cd:ba:03:02:01" UserPropPut

#删除openvpn账号的mac或者重置mac,以exampleuser用户为例
cd /usr/local/openvpn_as/scripts
./sacli --user "exampleuser" --key "pvt_hw_addr" UserPropDel

如需添加第三辅助地址的脚本如下(mac.py)以此类推

# this function is called by the Access Server after normal VPN or web authentication
def post_auth(authcred, attributes, authret, info):
    print("********** POST_AUTH %s %s %s %s" % (authcred, attributes, authret, info))

    # get user's property list, or create it if absent
    proplist = authret.setdefault('proplist', {})

    # user properties to save - we will use this to pass the hw_addr_save property to be
    # saved in the user property database.
    proplist_save = {}

    error = ""

    if attributes.get('vpn_auth'):                  # only do this for VPN authentication
        hw_addr = authcred.get('client_hw_addr')    # MAC address reported by the VPN client
        username = authcred.get('username')         # User name of the VPN client login attempt
        clientip = authcred.get('client_ip_addr')   # IP address of VPN client login attempt
        if hw_addr:
            hw_addr_save = proplist.get('pvt_hw_addr')           # saved MAC address (primary)
            hw_addr_save2 = proplist.get('pvt_hw_addr2')         # saved MAC address (secondary, manually added)
            hw_addr_save3 = proplist.get('pvt_hw_addr3')         # saved MAC address (third, manually added)

            if hw_addr_save:
                # Check if the MAC address matches any of the saved addresses
                if not hw_addr == hw_addr_save and not hw_addr == hw_addr_save2 and not hw_addr == hw_addr_save3:
                    error = "The hardware MAC/UUID address reported by this VPN client does not match the registered addresses."
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    if hw_addr_save3:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s, %s, or %s" % (hw_addr_save, hw_addr_save2, hw_addr_save3))
                    elif hw_addr_save2:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s or %s" % (hw_addr_save, hw_addr_save2))
                    else:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s" % hw_addr_save)
                    print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")
                else:
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    if hw_addr_save3:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s, %s, or %s" % (hw_addr_save, hw_addr_save2, hw_addr_save3))
                    elif hw_addr_save2:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s or %s" % (hw_addr_save, hw_addr_save2))
                    else:
                        print("***** POST_AUTH MAC CHECK: expected MAC/UUID address : %s" % hw_addr_save)
                    print("***** POST_AUTH MAC CHECK: connection attempt        : SUCCESS")

            else:
                # First login by this user, save MAC addr to pvt_hw_addr only.
                if not first_login_ip_addr or first_login_ip_addr == clientip:
                    proplist_save['pvt_hw_addr'] = hw_addr
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : %s" % hw_addr)
                    print("***** POST_AUTH MAC CHECK: action taken              : MAC address learned and locked.")
                    print("***** POST_AUTH MAC CHECK: connection attempt        : SUCCESS")
                else:
                    error = "Your attempt to login from an address not approved for MAC/UUID address registration has been denied."
                    print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
                    print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
                    print("***** POST_AUTH MAC CHECK: action taken              : attempt to register client MAC/UUID address from restricted address denied.")
                    print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")

        else:
            error = "VPN client is not reporting a MAC/UUID address. Please verify that a suitable OpenVPN client is being used."
            print("***** POST_AUTH MAC CHECK: account user name         : %s" % username)
            print("***** POST_AUTH MAC CHECK: client IP address         : %s" % clientip)
            print("***** POST_AUTH MAC CHECK: client MAC/UUID address   : NONE REPORTED")
            print("***** POST_AUTH MAC CHECK: action taken              : VPN connection denied with a suitable error message.")
            print("***** POST_AUTH MAC CHECK: connection attempt        : FAILED")

    # process error, if one occurred
    if error:
        authret['status'] = FAIL
        authret['reason'] = error          # this error string is written to the server log file
        authret['client_reason'] = error   # this error string is reported to the client user

    return authret, proplist_save

科学上网
openvpnas
许可协议: 
分享

相关文章

12月 17, 2024

节点搭建教程 Vmess + WebSocket + TLS + 网站伪装

本文介绍了如何搭建一个稳定防封、高速的节点,使用 Vmess 协议,并兼容多种客户端。教程简化了一些步骤,使其更加适合初学者,重点在于申请证书和配置 Nginx。用户需要准备一台 VPS、域名和基本的 Linux 知识。主要步骤包括安装 1Panel、设置 BBR 以及配置防火墙,还介绍了如何通过 3x-ui 控制面板添加节点和申请 SSL 证书。整体过程简单易操作,确保读者能成功搭建节点。

12月 9, 2024

FRP 内网穿透配置

本文介绍了如何使用FRP(Fast Reverse Proxy)进行内网穿透,以实现Windows远程桌面控制。文中详细说明了服务端(VPS)和客户端(Windows)的环境要求、配置步骤及安全建议,包括安装脚本、端口配置、防火墙设置和启动命令。此外,还提供了连接方法和故障排查建议,确保用户能够顺利搭建和维护远程桌面连接。

12月 1, 2024

Clash for Linux 工具

本文介绍了如何在Linux系统上安装和配置Clash工具以实现科学上网。通过一系列命令,用户可以下载Clash核心文件、解压并移动文件,设置代理端口及节点配置。文章还说明了如何修改配置文件以移除香港节点及设置相关的环境变量。此外,提供了使用systemd设置Clash开机自启动的步骤,包括创建服务文件和启用服务。

下一篇

容器基础操作

上一篇

OpenVPN Access Server 常用操作指令(附shell脚本方法)

最近更新

  • 1panel 部署
  • jumpserver 堡垒机部署
  • ubuntu 设置时间显示为24小时制
  • pritunl vpn 部署
  • dockovpn 部署

热门标签

nacos openvpnas 资源分享 docker oracle mysql ubuntu 开源项目 虚拟化 Linux

目录

©2025 瓜生花子八宝粥. 保留部分权利。

使用 Halo 主题 Chirpy