28
2024
11
14:42:55

五分钟搭建你的专属ocserv服务

选择 ocserv 原因

以下是市面上常见的几种VPN协议的简单对比:

  • PPTP(点对点隧道协议):这是最早的VPN协议之一,大部分操作系统都内置了对它的支持。但它的安全性较差,很容易被封锁,因此现在已经不推荐使用。

  • L2TP/IPSec(第二层隧道协议/安全IP):L2TP/IPSec相较于PPTP来说更为安全,但其流量特征明显,容易被防火长城检测并封锁。

  • OpenVPN:OpenVPN是目前最常用、最安全的VPN协议之一。它使用SSL/TLS进行密钥交换,可以提供非常高的安全性。但是,OpenVPN的流量特征也比较明显,因此有可能被防火长城封锁。

  • SSTP(安全套接字隧道协议):SSTP也是一个基于SSL的协议,其安全性较高。然而,SSTP主要被Windows系统支持,对于其他系统的支持性较差。

  • IKEv2(Internet Key Exchange version 2):IKEv2是一个非常安全且稳定的VPN协议,尤其适合移动设备。但是,像L2TP/IPSec一样,它的流量特征也较为明显,可能会被防火长城封锁。

  • ocserv(OpenConnect SSL VPN):ocserv使用的是Cisco的AnyConnect SSL VPN协议,这是一种在全球范围内广泛使用的协议,包括许多在中国大陆运营的外贸企业。它的流量特征和普通的HTTPS流量非常相似,这使得防火长城很难区分和封锁使用ocserv的VPN流量。所以,相比其他协议,ocserv的VPN服务更不容易被封锁。

用过很多种VPN也自己搭建过好几种,最稳定的就属于 ocserv,速度也是最快的,不好的地方就是不能使用 PAC,因为它是 VPN,不是代理软件

一键安装

本文更多是针对自己成果的存档,相关概念请自行谷歌学习。
我写了个一键部署脚本,在CentOS7以及CentOS8上测试通过,理论上也支持Ubuntu16及以上的系统。

sudo -i yum install wget -y && wget https://raw.githubusercontent.com/wangwanjie/ocserv-install/master/ocserv-install.sh && chmod +x ocserv-install.sh && ./ocserv-install.sh

首次执行脚本会提示安装或者退出,跟随指引一路走下去即可。
安装后再次运行脚本将出现如下菜单:

-> # ./ocserv-install.sh 检查是否安装了 ocserv ...
请选择要执行的功能:1) 升级 ocserv           5) 配置域名             9) 关闭 ocserv2) 卸载 ocserv           6) 查看ocserv登录日志  10) 查看 ocserv 状态3) 添加 ocserv 用户      7) 查看系统日志        11) 退出4) 移除 ocserv 用户      8) 启动或重启 ocserv#?

安装后事宜

安装后请执行命令“配置域名”,提前在服务商做好DNS解析为证书登录做准备。注意,配置域名这里只对阿里做了处理,其他服务商请自行准备ssl证书并填入ocserv配置文件,执行脚本重启 ocserv 即可。

脚本主要部分展示

主要部分

#!/bin/bash# 判断系统版本,根据不同系统选择不同的安装命令if cat /etc/os-release | grep -q "centos"; then
    PKG_MANAGER="yum"elif cat /etc/os-release | grep -q "ubuntu\|debian"; then
    PKG_MANAGER="apt-get"else
    echo "当前系统不受支持!"
    exit 1fi# Detect Debian users running the script with "sh" instead of bashif readlink /proc/$$/exe | grep -q "dash"; then
	echo 'This installer needs to be run with "bash", not "sh".'
	exitfi# Discard stdin. Needed when running from an one-liner which includes a newlineread -N 999999 -t 0.001# Detect OpenVZ 6if [[ $(uname -r | cut -d "." -f 1) -eq 2 ]]; then
	echo "The system is running an old kernel, which is incompatible with this installer."
	exitfi# Detect OS# $os_version variables aren't always in use, but are kept here for convenienceif grep -qs "ubuntu" /etc/os-release; then
	os="ubuntu"
	os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')
	group_name="nogroup"elif [[ -e /etc/debian_version ]]; then
	os="debian"
	os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
	group_name="nogroup"elif [[ -e /etc/almalinux-release || -e /etc/rocky-release || -e /etc/centos-release ]]; then
	os="centos"
	os_version=$(grep -shoE '[0-9]+' /etc/almalinux-release /etc/rocky-release /etc/centos-release | head -1)
	group_name="nobody"elif [[ -e /etc/fedora-release ]]; then
	os="fedora"
	os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1)
	group_name="nobody"else
	echo "This installer seems to be running on an unsupported distribution.
Supported distros are Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS and Fedora."
	exitfiif [[ "$os" == "ubuntu" && "$os_version" -lt 1804 ]]; then
	echo "Ubuntu 18.04 or higher is required to use this installer.
This version of Ubuntu is too old and unsupported."
	exitfiif [[ "$os" == "debian" && "$os_version" -lt 9 ]]; then
	echo "Debian 9 or higher is required to use this installer.
This version of Debian is too old and unsupported."
	exitfiif [[ "$os" == "centos" && "$os_version" -lt 7 ]]; then
	echo "CentOS 7 or higher is required to use this installer.
This version of CentOS is too old and unsupported."
	exitfi# Detect environments where $PATH does not include the sbin directoriesif ! grep -q sbin <<< "$PATH"; then
	echo '$PATH does not include sbin. Try using "su -" instead of "su".'
	exitfiif [[ "$EUID" -ne 0 ]]; then
	echo "This installer needs to be run with superuser privileges."
	exitfiif [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then
	echo "The system does not have the TUN device available.
TUN needs to be enabled before running this installer."
	exitfiOCSERV=/etc/ocservPORT=443ipv4_network="192.169.103.0"# 升级ocservfunction upgradeOcserv() {
    echo "升级 ocserv ..."

    # 根据系统使用合适的更新命令
    if [[ $PKG_MANAGER == "yum" ]]; then
        $PKG_MANAGER -y upgrade ocserv    else
        $PKG_MANAGER -y upgrade        $PKG_MANAGER -y install ocserv    fi

    echo "ocserv 升级完成!"}# 卸载ocservfunction uninstallOcserv() {
     read -p "此操作将会卸载 ocserv 及其所有相关文件和配置,确认执行吗? [y/n]: " confirm    if [[ "$confirm" = [yY] ]]; then
        echo "卸载 ocserv ..."
        $PKG_MANAGER -y remove ocserv        rm -rf $OCSERV/        rm -rf /root/anyconnect        rm -rf /var/www/html/user        rm -rf /var/lib/ocserv        echo "ocserv 卸载完成!"
    else
        echo "已取消操作。"
    fi}# 添加用户function addUser() {
    sudo /root/anyconnect/user_add.sh}# 移除用户function removeUser() {
    sudo /root/anyconnect/user_del.sh}# 启动或重启 ocservfunction startOrRestartOcserv() {
    if pgrep "ocserv" > /dev/null ; then
        echo "正在重启 ocserv ..."
        systemctl restart ocserv    else 
        echo "正在启动 ocserv ..."
        systemctl start ocserv    fi
    if pgrep "httpd" > /dev/null ; then
        echo "正在重启 httpd ..."
        sudo systemctl restart httpd    else 
        echo "正在启动 httpd ..."
        sudo systemctl start httpd    fi}# 关闭 ocservfunction stopOcserv() {
    echo "正在关闭 ocserv ..."
    systemctl stop ocserv}# 查看ocserv状态function statusOcserv() {
    systemctl status ocserv}# 配置 ipv4防火墙function configIpv4Firewall() {
    echo "配置 ipv4防火墙 ..."
    echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-custom.conf    read -p "是否开启bbr? [y/n]: " confirm    if [[ "$confirm" = [yY] ]]; then
        if [[ "$os" == "centos" ]]; then
                if [[ "$os_version" -eq "8" ]]; then
                    echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.d/60-custom.conf                    echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.d/60-custom.conf                elif [[ "$os_version" -eq "7" ]]; then
                    rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org                    rpm -Uvh https://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
                    yum --enablerepo=elrepo-kernel install kernel-ml -y
                    # sudo egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \'
                    # sudo grub2-set-default 0
                    # grub2-mkconfig -o /boot/grub2/grub.cfg
                fi
        elif [[ "$os" == "ubuntu" ]]; then
            echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.d/60-custom.conf            echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.d/60-custom.conf        else
            echo "Unsupported OS type."
            exit 1
        fi
    else
        echo "不安装bbr"
    fi
    
    sudo sysctl -p /etc/sysctl.d/60-custom.conf    # Check if firewall-cmd is installed
    if [ "$(which firewall-cmd)" ]; then
        echo "firewall-cmd is already installed."
    else
        if [[ "$os" == "centos" ]]; then
            if [[ "$os_version" -eq "8" ]]; then
                sudo dnf install firewalld -y
            elif [[ "$os_version" -eq "7" ]]; then
                sudo yum install firewalld -y
            fi
        elif [[ "$os" == "ubuntu" ]]; then
            sudo apt-get update            sudo apt-get install firewalld -y
        else
            echo "Unsupported OS type."
            exit 1
        fi
    fi
     # Start firewall-cmd and enable at boot
    sudo systemctl start firewalld    sudo systemctl enable firewalld    sudo firewall-cmd --permanent --add-port=$PORT/tcp    sudo firewall-cmd --permanent --add-port=$PORT/udp    sudo firewall-cmd --permanent --add-port=80/tcp    sudo firewall-cmd --permanent --add-service=https    sudo firewall-cmd --permanent --add-service=ssh    sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='${ipv4_network}/24' masquerade"
    sudo systemctl reload firewalld    echo "配置 ipv4防火墙结束,已重启防火墙"}function prepare() {if [[ "$os" == "centos" ]]; then
    if [[ "$os_version" -eq "8" ]]; then
        cd /etc/yum.repos.d/        sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*        sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*        wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
        yum clean all
        yum makecache        sudo yum install wget -y
        sudo yum install dnf -y
        sudo yum install expect -y

        sudo dnf install httpd -y
        sudo systemctl enable httpd        sudo dnf install epel-release -y
        sudo yum install -y gnutls-utils        sudo dnf install ocserv -y
    elif [[ "$os_version" -eq "7" ]]; then
        sudo yum install wget -y
        sudo yum install expect -y

        sudo yum install httpd -y
        sudo systemctl enable httpd        sudo yum install epel-release -y
        sudo yum install -y gnutls-utils        sudo yum install ocserv -y
    fielif [[ "$os" == "ubuntu" ]]; then
    sudo apt update    sudo apt install ocservfi
    get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
    read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip    # If the checkip service is unavailable and user didn't provide input, ask again
    until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
        echo "Invalid input."
        read -p "Public IPv4 address / hostname: " public_ip    done
    [[ -z "$public_ip" ]] && public_ip="$get_public_ip"

    echo "公网 IP:$public_ip"

    cd $OCSERV
    mkdir -p pki user config-per-group config-per-user defaults tmpl pem    mkdir -p /root/anyconnect   
    remote_repo=https://raw.githubusercontent.com/wangwanjie/ocserv-install    remote_repo_branch=master    rm -rf ocserv.conf connect-script config-per-group/* tmpl/* pem/*    wget --no-check-certificate $remote_repo/$remote_repo_branch/ocserv.conf    wget --no-check-certificate $remote_repo/$remote_repo_branch/connect-script    wget --no-check-certificate $remote_repo/$remote_repo_branch/config-per-group/main -O config-per-group/main    wget --no-check-certificate $remote_repo/$remote_repo_branch/config-per-group/others -O config-per-group/others    chmod +x connect-script    cd /root/anyconnect    wget --no-check-certificate $remote_repo/$remote_repo_branch/gen-client-cert.sh    wget --no-check-certificate $remote_repo/$remote_repo_branch/user_add.sh    wget --no-check-certificate $remote_repo/$remote_repo_branch/user_del.sh    chmod +x gen-client-cert.sh    chmod +x user_add.sh    chmod +x user_del.shread -p "请输入证书签发组织名称 [vanjay.cn]: " sign_org[[ -z "$sign_org" ]] && sign_org="vanjay.cn"read -p "请输入证书有效期(天) [3650]: " cert_valid_days[[ -z "$cert_valid_days" ]] && cert_valid_days="3650"

    cd $OCSERV/tmplcat >ca.tmpl <<EOF
cn = "VanJay AnyConnect CA"
organization = "$sign_org"
serial = 1
expiration_days = $cert_valid_daysca
signing_key
cert_signing_key
crl_signing_key
EOFcat >server.tmpl <<EOF
cn = "VanJay AnyConnect CA"
organization = "$sign_org"
serial = 2
expiration_days = $cert_valid_daysencryption_key
signing_key
tls_www_server
EOFcat << _EOF_ >crl.tmplcrl_next_update = 365
crl_number = 1
_EOF_}function configDomain() {
    read -p "请输入 VPN 域名!(默认为 tz.vanjay.cn): " domain_name    if [ -z "$domain_name" ]; then
        domain_name="tz.vanjay.cn"
    fi

    read -p "请输入您的 Email!(默认为 396736694@qq.com): " mail_address    if [ -z "$mail_address" ]; then
        mail_address="396736694@qq.com"
    fi

    while true; do
        read -p "请输入ali_key: " ali_key        if [[ -n "$ali_key" ]]; then
            break
        else
            echo "无效的 ali_key"
        fi
    done

    while true; do
        read -p "请输入ali_secret: " ali_secret        if [[ -n "$ali_secret" ]]; then
            break
        else
            echo "无效的 ali_secret"
        fi
    done

    export Ali_Key=$ali_key
    export Ali_Secret=$ali_secret

    yum install socat -y

    curl https://get.acme.sh | sh
    export PATH="$PATH:$HOME/.acme.sh"
    alias acme.sh=~/.acme.sh/acme.sh
    acme.sh  --register-account  -m $mail_address --server zerossl
    acme.sh --issue --dns dns_ali -d $domain_name
    mkdir -p $OCSERV/pki    cp -Rf ~/.acme.sh/${domain_name}_ecc/ $OCSERV/pki    cer_path=$OCSERV/pki/${domain_name}_ecc/${domain_name}.cer    key_path=$OCSERV/pki/${domain_name}_ecc/${domain_name}.key    # 更新 ocserv.conf 文件
    sed -i "s#\(server-cert = \).*#\1$cer_path#" $OCSERV/ocserv.conf    sed -i "s#\(server-key = \).*#\1$key_path#" $OCSERV/ocserv.conf    sed -i "s#\(default-domain = \).*#\1$domain_name#" $OCSERV/ocserv.conf

    startOrRestartOcserv    echo "已修改 ocserv.conf,已重启 ocserv 服务"} function generate_server_cert() {
    cd $OCSERV/pem    # 生成 CA 证书
    certtool --generate-privkey --outfile ca-key.pem

    certtool --generate-self-signed --load-privkey ca-key.pem --template $OCSERV/tmpl/ca.tmpl --outfile ca-cert.pem    # 生成本地服务器证书
    certtool --generate-privkey --outfile server-key.pem

    certtool --generate-certificate --load-privkey server-key.pem \
    --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem \
    --template $OCSERV/tmpl/server.tmpl --outfile server-cert.pem    # 生成证书注销文件
    touch $OCSERV/pem/revoked.pem

    certtool --generate-crl --load-ca-privkey ca-key.pem \
            --load-ca-certificate ca-cert.pem \
            --template $OCSERV/tmpl/crl.tmpl --outfile crl.pem}function useSystemDNS() {
    sed -i -e "/^#*\s*dns\s*=.*$/d" $OCSERV/ocserv.conf    # Locate the proper resolv.conf
    # Needed for systems running systemd-resolved
    if grep '^nameserver' "/etc/resolv.conf" | grep -qv '127.0.0.53' ; then
        resolv_conf="/etc/resolv.conf"
    else
        resolv_conf="/run/systemd/resolve/resolv.conf"
    fi
    # Obtain the resolvers from resolv.conf and use them for OpenVPN
    grep -v '^#\|^;' "$resolv_conf" | grep '^nameserver' | grep -v '127.0.0.53' | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | while read line; do
        echo "\ndns = $line" >> $OCSERV/ocserv.conf    done}function useOtherDNS() {
    sed -i "s|dns = 1.1.1.1|dns = $1|g" $OCSERV/ocserv.conf    sed -i "s|dns = 8.8.8.8 # the second|dns = $2|g" $OCSERV/ocserv.conf}# 配置 ocserv.conffunction configOcserv() {
    read -p "请输入要监听的端口号(推荐使用80或443或10443)[443]: " PORT    until [[ -z "$PORT" || "$PORT" =~ ^[0-9]+$ && "$PORT" -le 65535 ]]; do
		echo "$PORT: invalid port."
		read -p "Port [443]: " PORT	done
	[[ -z "$PORT" ]] && PORT="443"

    echo "请选择DNS:"
    select FUNC in "Current system resolvers" "Google" "1.1.1.1" "Google & 1.1.1.1" "OpenDNS" "Quad9" "AdGuard"; do
        case $FUNC in
            "Current system resolvers" ) useSystemDNS; break;;
            "Google" ) useOtherDNS 8.8.8.8 8.8.4.4; break;;
            "1.1.1.1" ) useOtherDNS 1.1.1.1 1.0.0.1; break;;
            "Google & 1.1.1.1" ) useOtherDNS 1.1.1.1 8.8.8.8; break;;
            "OpenDNS" ) useOtherDNS 208.67.222.222 208.67.220.220; break;;
            "Quad9" ) useOtherDNS 9.9.9.9 149.112.112.112; break;;
            "AdGuard" ) useOtherDNS 94.140.14.14 94.140.15.15; break;;
        esac
    done

    until [[ $valid_ip == true ]]
    do
        read -p "请输入 ipv4_network [192.168.103.0]: " ipv4_network        [[ -z "$ipv4_network" ]] && ipv4_network="192.168.103.0"

        valid_ip=true        IFS='.' read -ra ip_array <<< "$ipv4_network"
        if [[ ${#ip_array[@]} -ne 4 ]]; then
            valid_ip=false        else
            for (( i=0; i<${#ip_array[@]}; i++ ))
            do
                octet=${ip_array[i]}
                if [[ "$i" -eq 0 ]]; then
                    if [[ "$octet" -eq 0 ]]; then
                        echo "$i ----- $octet"
                        valid_ip=false                        break
                    else
                        # 判断第一个分段是否为1到3位数字,且不能以0开头
                        if [[ ! "$octet" =~ ^[1-9][0-9]{0,2}$ ]]; then
                            valid_ip=false                            break
                        fi
                    fi
                else
                    # 判断每个分段是否为1到3位数字,可以以0开头
                    if [[ ! "$octet" =~ ^([0-9]|[1-9][0-9]{1,2})$ ]]; then
                        valid_ip=false                        break
                    elif [[ "$octet" -lt 0 || "$octet" -gt 255 ]]; then
                        valid_ip=false                        break
                    fi
                fi
            done
        fi

        if [[ $valid_ip == false ]]; then
            echo "输入的IP地址不合法,请重新输入!"
        fi
    done

    sed -i "s|tcp-port = 443|tcp-port = $PORT|g" $OCSERV/ocserv.conf    sed -i "s|udp-port = 443|udp-port = $PORT|g" $OCSERV/ocserv.conf    sed -i "s|ipv4-network = 192.168.103.0|ipv4-network = $ipv4_network|g" $OCSERV/ocserv.conf    if [[ -n "$public_ip" ]]; then
        sed -i "s/47.242.201.43/$public_ip/g" $OCSERV/ocserv.conf    fi

    echo "ocserv配置修改成功!"}# 启用开机自启function enableAutoStart() {
    echo "是否开启开机自启?(yes或no)"
    select yn in "yes" "no"; do
        case $yn in
            yes ) systemctl enable ocserv; break;;
            no ) break;;
        esac
    done}function logOcserv() {
    if [ -f /etc/ocserv/login.log ]; then
        tail -f /etc/ocserv/login.log    else
        echo "Error: /etc/ocserv/login.log not found!"
    fi }function logSystem() {
     if [ -f /var/log/messages ]; then
        tail -f /var/log/messages    else
        echo "Error: /var/log/messages not found!"
    fi }# 安装ocservecho "检查是否安装了 ocserv ..."if ! hash ocserv 2>/dev/null; then
    echo "ocserv 未安装!"
    echo "请选择安装 ocserv 或退出:"
    select yn in "安装" "退出"; do
        case $yn in
            安装 ) break;;
            退出 ) exit;;
        esac
    done

    # 根据系统使用合适的安装命令
    if [[ $PKG_MANAGER == "yum" ]]; then
        $PKG_MANAGER -y upgrade        $PKG_MANAGER -y install epel-release        $PKG_MANAGER -y install ocserv    else
        sudo -i 
        $PKG_MANAGER install wget -y 
        $PKG_MANAGER -y update        $PKG_MANAGER install epel-release wget -y
        $PKG_MANAGER install ocserv httpd -y
    fi

    prepare
    generate_server_cert
    configOcserv
    configIpv4Firewall
    enableAutoStart    echo "ocserv 安装完成!"else
    # 主程序
    echo "请选择要执行的功能:"
    select FUNC in "升级 ocserv" "卸载 ocserv" "添加 ocserv 用户" "移除 ocserv 用户" "配置域名" "查看ocserv登录日志" "查看系统日志" "启动或重启 ocserv" "关闭 ocserv" "查看 ocserv 状态" "退出"; do
        case $FUNC in
            "升级 ocserv" ) upgradeOcserv; break;;
            "卸载 ocserv" ) uninstallOcserv; break;;
            "添加 ocserv 用户" ) addUser; break;;
            "移除 ocserv 用户" ) removeUser; break;;
            "配置域名" ) configDomain; break;;
            "查看ocserv登录日志" ) logOcserv; break;;
            "查看系统日志" ) logSystem; break;;
            "启动或重启 ocserv" ) startOrRestartOcserv; break;;
            "关闭 ocserv" ) stopOcserv; break;;
            "查看 ocserv 状态" ) statusOcserv; break;;
            "退出" ) exit;;
        esac
    donefiecho "ocserv 脚本运行结束!"echo "再次运行此脚本可选择功能!"

生成证书

#!/bin/bash# 检查是否使用 root 账户执行脚本if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root."
   exit 1fi# 从命令行参数获取用户名和路径USER=$1OCSERV=$2USER_DIR=$OCSERV/user/$USER# 确保目录存在mkdir -p $USER_DIR && cd $USER_DIR# 生成私钥SERIAL=`date +%s`certtool --generate-privkey --outfile $USER-key.pem# 生成证书的模板文件cat << _EOF_ >$USER.tmplcn = "$USER"
unit = "users"
serial = "$SERIAL"
expiration_days = 9999
signing_key
tls_www_client
_EOF_# 用私钥、证书模板以及根证书生成证书文件cd $USER_DIRcerttool --generate-certificate --load-privkey $USER-key.pem --load-ca-certificate $OCSERV/pem/ca-cert.pem --load-ca-privkey $OCSERV/pem/ca-key.pem --template $USER.tmpl --outfile $USER-cert.pem# 将证书文件导出为 p12 格式openssl pkcs12 -export -inkey $USER-key.pem -in $USER-cert.pem -name "$USER VPN Client Cert" -certfile $OCSERV/pem/ca-cert.pem -out $USER.p12

添加用户

#!/bin/bash# 这个脚本是用来同时添加 VPN 用户和他们的证书的# 检查是否使用 root 账户执行脚本if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root."
   exit 1fifunction input_user() {
	
	# 从两个数据源获取服务器的公网 IP
	get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
	public_ip="$get_public_ip"

	# 如果第一个数据源没有返回正确的公网 IP,就尝试第二个数据源
	if [[ -z "$public_ip" ]]; then
		public_ip=$(lynx --source www.monip.org | sed -nre 's/^.* (([0-9]{1,3}\.){3}[0-9]{1,3}).*$/\1/p')
	fi

	# 从 ocserv.conf 文件中获取 VPN 端口号
	PORT=$(grep ^\s*tcp-port /etc/ocserv/ocserv.conf | awk '{print $NF}')

	# 获取 VPN 用户名和组别
	read -p "请输入您的 VPN 用户名: " user_name	if  [[ ! -n "$user_name" ]]; then
		echo "您没有输入用户名,请重新执行程序"
	else
		read -p "请输入您的 VPN 用户组别: " user_group	fi

	# 获取 VPN 用户密码
	if [[ ! -n "$user_group" ]]; then
		echo "您没有输入用户组别,将使用配置文件中的默认组别"
		user_group="others"
	fi
	
	read -p "请输入您的密码: " user_pass	if [[ ! -n "$user_pass" ]]; then
		echo "您没有输入密码,请重新执行程序"
	else
		user_add
		cert_add	fi}function user_add() {
	# 根据不同的系统,选择不同的 expect 路径
	if [ -x "$(command -v yum)" ]; then
		EXPECT_CMD="/usr/bin/expect"
	else
		EXPECT_CMD="/usr/bin/env expect"
	fi

	sudo touch /etc/ocserv/ocpasswd	sudo chmod 600 /etc/ocserv/ocpasswd	$EXPECT_CMD <<-END
	spawn sudo ocpasswd -c /etc/ocserv/ocpasswd -g $user_group $user_name 
	expect "Enter password:"
	send "$user_pass\r"
	expect "Re-enter password:"
	send "$user_pass\r"
	expect eof	exit
	END}# 为用户添加证书function cert_add() {
	OCSERV=/etc/ocserv	user_root_dir=$OCSERV/user	mkdir -p $user_root_dir/$user_name
	cd $user_root_dir/$user_name

	# 根据不同的系统,选择不同的 expect 路径
	if [ -x "$(command -v yum)" ]; then
		EXPECT_CMD="/usr/bin/expect"
	else
		EXPECT_CMD="/usr/bin/env expect"
	fi

	$EXPECT_CMD <<-END
	spawn sudo /root/anyconnect/gen-client-cert.sh $user_name $OCSERV
	expect "Enter Export Password:"
	send "$user_pass\r"
	expect "Verifying - Enter Export Password:"
	send "$user_pass\r"
	expect eof	exit
	END	cd $user_root_dir && mkdir -p /var/www/html/user    cp -R $user_name /var/www/html/user/$user_name
	echo "$user_name 用户已成功创建,密码为 $user_pass"
	echo "$user_name 的证书已成功创建,请点击以下链接进行下载。"
	echo "http://$public_ip/user/$user_name/$user_name.p12"
	echo "证书本地路径为:$user_root_dir/$user_name"
	echo "导入证书的密码是 $user_pass"
	echo "VPN 地址和端口是 $public_ip:$PORT"}# 安装 shellfunction shell_install() {
	input_user}shell_install

删除用户

#!/bin/bash# ocserv 删除用户及注销用户的证书脚本文件# 检查是否使用 root 账户执行脚本if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root."
   exit 1fifunction user_del() {
    OCSERV=/etc/ocserv    
    # 获取要删除用户的用户名
    read -p "请输入您想要删除的用户名!" user_name    if  [[ ! -n "$user_name" ]]; then
        echo "您没有输入用户名,请重新执行程序"
    else
        # 使用 ocpasswd 命令删除用户
        /usr/bin/ocpasswd -d $user_name
        echo "$user_name 用户已成功删除"
        
        # 将用户证书添加到撤销列表,并生成 CRL 文件
        cat $OCSERV/user/$user_name/$user_name-cert.pem >> $OCSERV/pem/revoked.pem
        certtool --generate-crl --load-ca-privkey $OCSERV/pem/ca-key.pem  --load-ca-certificate $OCSERV/pem/ca-cert.pem --load-certificate $OCSERV/pem/revoked.pem  --template $OCSERV/tmpl/crl.tmpl --outfile $OCSERV/pem/crl.pem        echo "$user_name 用户的证书已被注销"
        
        # 重启 ocserv 服务
        systemctl restart ocserv.service    fi}# 调用函数user_del

脚本

脚本已开源,如有定制需求可以fork自行修改。

ocserv-install

相关常用命令

journalctl -u ocserv -fsystemctl reload firewalld
firewall-cmd --list-all
systemctl enable firewalld
systemctl disable firewalld
systemctl start firewalld
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=xxx/tcp
firewall-cmd --permanent --remove-port=xxx/tcp
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='your_ipv4_mask/24' masquerade"

资料

ocserv开源代码

OpenConnect

OpenConnect GUI

官方配置说明

客户端下载

可以使用 OpenConnect GUI 也可以使用 openconnect 命令行连接,使用方法自行搜索。
推荐使用 Cisco Anyconnect 或者 Cisco Secure Client 连接,下载链接




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

以下内容需要兑换:

本文链接:https://hqyman.cn/post/8633.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: