12.1 概述

随着云计算的普及,将OpenVPN与各种云服务集成已成为企业网络架构的重要组成部分。本章将探讨如何在主流云平台上部署OpenVPN,以及如何将OpenVPN与云服务集成,实现安全、高效的混合云网络架构。

graph TD
    A[OpenVPN与云服务集成] --> B[主流云平台部署]
    A --> C[混合云网络架构]
    A --> D[云原生部署模式]
    A --> E[自动化与编排]
    A --> F[安全与合规]
    A --> G[监控与管理]
    A --> H[灾备与高可用]
    
    B --> B1[AWS部署]
    B --> B2[Azure部署]
    B --> B3[GCP部署]
    B --> B4[阿里云部署]
    
    C --> C1[站点到云VPN]
    C --> C2[多云连接]
    C --> C3[云间网络隔离]
    
    D --> D1[容器化部署]
    D --> D2[Kubernetes集成]
    D --> D3[Serverless VPN]
    
    E --> E1[基础设施即代码]
    E --> E2[CI/CD管道集成]
    E --> E3[自动扩展配置]
    
    F --> F1[云平台安全组配置]
    F --> F2[IAM集成]
    F --> F3[合规性考量]
    
    G --> G1[云监控集成]
    G --> G2[日志聚合与分析]
    G --> G3[性能监控]
    
    H --> H1[跨区域部署]
    H --> H2[灾难恢复策略]
    H --> H3[自动故障转移]

12.2 主流云平台部署

12.2.1 AWS部署

在AWS上部署OpenVPN服务器:

#!/bin/bash
# aws_openvpn_deploy.sh

# 设置变量
REGION="us-east-1"
VPC_CIDR="10.0.0.0/16"
SUBNET_CIDR="10.0.1.0/24"
AVAILABILITY_ZONE="us-east-1a"
INSTANCE_TYPE="t3.small"
KEY_NAME="openvpn-key"
AMI_ID="ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI ID
VPN_NETWORK="172.16.0.0/24"

# 创建VPC
echo "创建VPC..."
VPC_ID=$(aws ec2 create-vpc \
    --cidr-block $VPC_CIDR \
    --region $REGION \
    --query 'Vpc.VpcId' \
    --output text)

aws ec2 create-tags \
    --resources $VPC_ID \
    --tags Key=Name,Value=OpenVPN-VPC \
    --region $REGION

echo "VPC创建完成: $VPC_ID"

# 创建互联网网关
echo "创建互联网网关..."
IGW_ID=$(aws ec2 create-internet-gateway \
    --region $REGION \
    --query 'InternetGateway.InternetGatewayId' \
    --output text)

aws ec2 create-tags \
    --resources $IGW_ID \
    --tags Key=Name,Value=OpenVPN-IGW \
    --region $REGION

# 将互联网网关附加到VPC
aws ec2 attach-internet-gateway \
    --internet-gateway-id $IGW_ID \
    --vpc-id $VPC_ID \
    --region $REGION

echo "互联网网关创建并附加完成: $IGW_ID"

# 创建子网
echo "创建子网..."
SUBNET_ID=$(aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block $SUBNET_CIDR \
    --availability-zone $AVAILABILITY_ZONE \
    --region $REGION \
    --query 'Subnet.SubnetId' \
    --output text)

aws ec2 create-tags \
    --resources $SUBNET_ID \
    --tags Key=Name,Value=OpenVPN-Subnet \
    --region $REGION

echo "子网创建完成: $SUBNET_ID"

# 创建路由表
echo "创建路由表..."
ROUTE_TABLE_ID=$(aws ec2 create-route-table \
    --vpc-id $VPC_ID \
    --region $REGION \
    --query 'RouteTable.RouteTableId' \
    --output text)

aws ec2 create-tags \
    --resources $ROUTE_TABLE_ID \
    --tags Key=Name,Value=OpenVPN-RouteTable \
    --region $REGION

# 创建到互联网的路由
aws ec2 create-route \
    --route-table-id $ROUTE_TABLE_ID \
    --destination-cidr-block 0.0.0.0/0 \
    --gateway-id $IGW_ID \
    --region $REGION

# 将路由表与子网关联
aws ec2 associate-route-table \
    --route-table-id $ROUTE_TABLE_ID \
    --subnet-id $SUBNET_ID \
    --region $REGION

echo "路由表创建并配置完成: $ROUTE_TABLE_ID"

# 创建安全组
echo "创建安全组..."
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
    --group-name OpenVPN-SG \
    --description "Security group for OpenVPN server" \
    --vpc-id $VPC_ID \
    --region $REGION \
    --query 'GroupId' \
    --output text)

aws ec2 create-tags \
    --resources $SECURITY_GROUP_ID \
    --tags Key=Name,Value=OpenVPN-SG \
    --region $REGION

# 配置安全组规则
aws ec2 authorize-security-group-ingress \
    --group-id $SECURITY_GROUP_ID \
    --protocol tcp \
    --port 22 \
    --cidr 0.0.0.0/0 \
    --region $REGION

aws ec2 authorize-security-group-ingress \
    --group-id $SECURITY_GROUP_ID \
    --protocol udp \
    --port 1194 \
    --cidr 0.0.0.0/0 \
    --region $REGION

aws ec2 authorize-security-group-ingress \
    --group-id $SECURITY_GROUP_ID \
    --protocol tcp \
    --port 443 \
    --cidr 0.0.0.0/0 \
    --region $REGION

echo "安全组创建并配置完成: $SECURITY_GROUP_ID"

# 创建EC2实例
echo "创建EC2实例..."
INSTANCE_ID=$(aws ec2 run-instances \
    --image-id $AMI_ID \
    --instance-type $INSTANCE_TYPE \
    --key-name $KEY_NAME \
    --security-group-ids $SECURITY_GROUP_ID \
    --subnet-id $SUBNET_ID \
    --associate-public-ip-address \
    --user-data file://openvpn_userdata.sh \
    --region $REGION \
    --query 'Instances[0].InstanceId' \
    --output text)

aws ec2 create-tags \
    --resources $INSTANCE_ID \
    --tags Key=Name,Value=OpenVPN-Server \
    --region $REGION

echo "EC2实例创建完成: $INSTANCE_ID"

# 等待实例运行
echo "等待实例运行..."
aws ec2 wait instance-running \
    --instance-ids $INSTANCE_ID \
    --region $REGION

# 获取实例公共IP
PUBLIC_IP=$(aws ec2 describe-instances \
    --instance-ids $INSTANCE_ID \
    --region $REGION \
    --query 'Reservations[0].Instances[0].PublicIpAddress' \
    --output text)

echo "OpenVPN服务器部署完成!"
echo "服务器公共IP: $PUBLIC_IP"
echo "使用以下命令连接到服务器:"
echo "ssh -i $KEY_NAME.pem ec2-user@$PUBLIC_IP"
echo "OpenVPN配置将在约5-10分钟后完成"
echo "完成后,您可以使用SCP下载客户端配置文件:"
echo "scp -i $KEY_NAME.pem ec2-user@$PUBLIC_IP:/home/ec2-user/client.ovpn ."

用户数据脚本 openvpn_userdata.sh

#!/bin/bash
# openvpn_userdata.sh

# 更新系统并安装依赖
yum update -y
yum install -y epel-release
yum install -y openvpn easy-rsa

# 设置Easy-RSA
cp -r /usr/share/easy-rsa/3.0/* /etc/openvpn/
cd /etc/openvpn

# 初始化PKI
./easyrsa init-pki

# 创建CA(无需交互)
EASYRSA_BATCH=1 ./easyrsa build-ca nopass

# 创建服务器证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass

# 创建Diffie-Hellman参数
./easyrsa gen-dh

# 创建TLS认证密钥
openvpn --genkey --secret /etc/openvpn/pki/ta.key

# 创建客户端证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-client-full client nopass

# 配置OpenVPN服务器
cat > /etc/openvpn/server.conf << EOF
port 1194
proto udp
dev tun

ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/server.crt
key /etc/openvpn/pki/private/server.key
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key 0

server 172.16.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

keepalive 10 120
cipher AES-256-GCM
auth SHA256
compress lz4-v2
push "compress lz4-v2"

user nobody
group nobody

persist-key
persist-tun

status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3
EOF

# 创建日志目录
mkdir -p /var/log/openvpn

# 创建客户端配置
cat > /home/ec2-user/client.ovpn << EOF
client
dev tun
proto udp
remote $(curl -s http://169.254.169.254/latest/meta-data/public-ipv4) 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
compress lz4-v2
verb 3

<ca>
$(cat /etc/openvpn/pki/ca.crt)
</ca>

<cert>
$(cat /etc/openvpn/pki/issued/client.crt)
</cert>

<key>
$(cat /etc/openvpn/pki/private/client.key)
</key>

<tls-auth>
$(cat /etc/openvpn/pki/ta.key)
</tls-auth>
key-direction 1
EOF

# 设置权限
chown ec2-user:ec2-user /home/ec2-user/client.ovpn
chmod 600 /home/ec2-user/client.ovpn

# 启用IP转发
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
sysctl -p /etc/sysctl.d/99-openvpn.conf

# 配置iptables
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE

# 保存iptables规则
yum install -y iptables-services
systemctl enable iptables
service iptables save

# 启动OpenVPN服务
systemctl enable openvpn@server
systemctl start openvpn@server

# 安装Web管理界面(可选)
yum install -y nginx php php-fpm
systemctl enable nginx php-fpm
systemctl start nginx php-fpm

echo "OpenVPN服务器设置完成"

12.2.2 Azure部署

使用Azure CLI部署OpenVPN服务器:

#!/bin/bash
# azure_openvpn_deploy.sh

# 设置变量
RESOURCE_GROUP="OpenVPN-RG"
LOCATION="eastus"
VNET_NAME="OpenVPN-VNet"
SUBNET_NAME="OpenVPN-Subnet"
NSG_NAME="OpenVPN-NSG"
PUBLIC_IP_NAME="OpenVPN-PublicIP"
NIC_NAME="OpenVPN-NIC"
VM_NAME="OpenVPN-Server"
VM_SIZE="Standard_B2s"
ADMIN_USERNAME="azureuser"
VPN_NETWORK="172.16.0.0/24"

# 创建资源组
echo "创建资源组..."
az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION

# 创建虚拟网络和子网
echo "创建虚拟网络和子网..."
az network vnet create \
    --resource-group $RESOURCE_GROUP \
    --name $VNET_NAME \
    --address-prefix 10.0.0.0/16 \
    --subnet-name $SUBNET_NAME \
    --subnet-prefix 10.0.1.0/24

# 创建网络安全组
echo "创建网络安全组..."
az network nsg create \
    --resource-group $RESOURCE_GROUP \
    --name $NSG_NAME

# 添加安全规则
az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name SSH \
    --priority 1000 \
    --protocol Tcp \
    --destination-port-range 22 \
    --access Allow

az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name OpenVPN-UDP \
    --priority 1010 \
    --protocol Udp \
    --destination-port-range 1194 \
    --access Allow

az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name HTTPS \
    --priority 1020 \
    --protocol Tcp \
    --destination-port-range 443 \
    --access Allow

# 创建公共IP地址
echo "创建公共IP地址..."
az network public-ip create \
    --resource-group $RESOURCE_GROUP \
    --name $PUBLIC_IP_NAME \
    --allocation-method Static

# 创建网络接口
echo "创建网络接口..."
az network nic create \
    --resource-group $RESOURCE_GROUP \
    --name $NIC_NAME \
    --vnet-name $VNET_NAME \
    --subnet $SUBNET_NAME \
    --network-security-group $NSG_NAME \
    --public-ip-address $PUBLIC_IP_NAME

# 生成SSH密钥对
echo "生成SSH密钥对..."
ssh-keygen -t rsa -b 2048 -f ./azure_openvpn_key -N ""

# 创建虚拟机
echo "创建虚拟机..."
az vm create \
    --resource-group $RESOURCE_GROUP \
    --name $VM_NAME \
    --nics $NIC_NAME \
    --image UbuntuLTS \
    --size $VM_SIZE \
    --admin-username $ADMIN_USERNAME \
    --ssh-key-value ./azure_openvpn_key.pub \
    --custom-data ./azure_openvpn_cloud_init.txt

# 获取公共IP地址
PUBLIC_IP=$(az network public-ip show \
    --resource-group $RESOURCE_GROUP \
    --name $PUBLIC_IP_NAME \
    --query ipAddress \
    --output tsv)

echo "OpenVPN服务器部署完成!"
echo "服务器公共IP: $PUBLIC_IP"
echo "使用以下命令连接到服务器:"
echo "ssh -i azure_openvpn_key $ADMIN_USERNAME@$PUBLIC_IP"
echo "OpenVPN配置将在约5-10分钟后完成"
echo "完成后,您可以使用SCP下载客户端配置文件:"
echo "scp -i azure_openvpn_key $ADMIN_USERNAME@$PUBLIC_IP:/home/$ADMIN_USERNAME/client.ovpn ."

Cloud-init配置文件 azure_openvpn_cloud_init.txt

#cloud-config
package_update: true
package_upgrade: true

packages:
  - openvpn
  - easy-rsa
  - iptables-persistent
  - net-tools

write_files:
  - path: /etc/openvpn/setup.sh
    permissions: '0755'
    content: |
      #!/bin/bash
      # 设置Easy-RSA
      mkdir -p /etc/openvpn/easy-rsa
      cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
      cd /etc/openvpn/easy-rsa

      # 初始化PKI
      ./easyrsa init-pki

      # 创建CA(无需交互)
      EASYRSA_BATCH=1 ./easyrsa build-ca nopass

      # 创建服务器证书和密钥
      EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass

      # 创建Diffie-Hellman参数
      ./easyrsa gen-dh

      # 创建TLS认证密钥
      openvpn --genkey --secret /etc/openvpn/pki/ta.key

      # 创建客户端证书和密钥
      EASYRSA_BATCH=1 ./easyrsa build-client-full client nopass

      # 配置OpenVPN服务器
      cat > /etc/openvpn/server.conf << EOF
      port 1194
      proto udp
      dev tun

      ca /etc/openvpn/easy-rsa/pki/ca.crt
      cert /etc/openvpn/easy-rsa/pki/issued/server.crt
      key /etc/openvpn/easy-rsa/pki/private/server.key
      dh /etc/openvpn/easy-rsa/pki/dh.pem
      tls-auth /etc/openvpn/pki/ta.key 0

      server 172.16.0.0 255.255.255.0
      push "redirect-gateway def1 bypass-dhcp"
      push "dhcp-option DNS 8.8.8.8"
      push "dhcp-option DNS 8.8.4.4"

      keepalive 10 120
      cipher AES-256-GCM
      auth SHA256
      compress lz4-v2
      push "compress lz4-v2"

      user nobody
      group nogroup

      persist-key
      persist-tun

      status /var/log/openvpn/status.log
      log-append /var/log/openvpn/openvpn.log
      verb 3
      EOF

      # 创建日志目录
      mkdir -p /var/log/openvpn

      # 获取公共IP地址
      PUBLIC_IP=$(curl -s https://api.ipify.org)

      # 创建客户端配置
      cat > /home/azureuser/client.ovpn << EOF
      client
      dev tun
      proto udp
      remote $PUBLIC_IP 1194
      resolv-retry infinite
      nobind
      persist-key
      persist-tun
      remote-cert-tls server
      cipher AES-256-GCM
      auth SHA256
      compress lz4-v2
      verb 3

      <ca>
      $(cat /etc/openvpn/easy-rsa/pki/ca.crt)
      </ca>

      <cert>
      $(cat /etc/openvpn/easy-rsa/pki/issued/client.crt)
      </cert>

      <key>
      $(cat /etc/openvpn/easy-rsa/pki/private/client.key)
      </key>

      <tls-auth>
      $(cat /etc/openvpn/pki/ta.key)
      </tls-auth>
      key-direction 1
      EOF

      # 设置权限
      chown azureuser:azureuser /home/azureuser/client.ovpn
      chmod 600 /home/azureuser/client.ovpn

      # 启用IP转发
      echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
      sysctl -p /etc/sysctl.d/99-openvpn.conf

      # 配置iptables
      iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE

      # 保存iptables规则
      netfilter-persistent save
      netfilter-persistent reload

      # 启动OpenVPN服务
      systemctl enable openvpn@server
      systemctl start openvpn@server

      echo "OpenVPN服务器设置完成"

runcmd:
  - bash /etc/openvpn/setup.sh

12.2.3 GCP部署

使用Google Cloud CLI部署OpenVPN服务器:

#!/bin/bash
# gcp_openvpn_deploy.sh

# 设置变量
PROJECT_ID="your-project-id"
REGION="us-central1"
ZONE="us-central1-a"
VPC_NAME="openvpn-vpc"
SUBNET_NAME="openvpn-subnet"
SUBNET_RANGE="10.0.0.0/24"
FIREWALL_NAME="openvpn-firewall"
INSTANCE_NAME="openvpn-server"
MACHINE_TYPE="e2-small"
VPN_NETWORK="172.16.0.0/24"

# 设置项目
gcloud config set project $PROJECT_ID

# 创建VPC网络
echo "创建VPC网络..."
gcloud compute networks create $VPC_NAME \
    --subnet-mode=custom

# 创建子网
echo "创建子网..."
gcloud compute networks subnets create $SUBNET_NAME \
    --network=$VPC_NAME \
    --region=$REGION \
    --range=$SUBNET_RANGE

# 创建防火墙规则
echo "创建防火墙规则..."
gcloud compute firewall-rules create $FIREWALL_NAME-ssh \
    --network=$VPC_NAME \
    --allow=tcp:22 \
    --source-ranges=0.0.0.0/0 \
    --description="Allow SSH from anywhere"

gcloud compute firewall-rules create $FIREWALL_NAME-openvpn \
    --network=$VPC_NAME \
    --allow=udp:1194 \
    --source-ranges=0.0.0.0/0 \
    --description="Allow OpenVPN from anywhere"

gcloud compute firewall-rules create $FIREWALL_NAME-https \
    --network=$VPC_NAME \
    --allow=tcp:443 \
    --source-ranges=0.0.0.0/0 \
    --description="Allow HTTPS from anywhere"

# 创建实例
echo "创建实例..."
gcloud compute instances create $INSTANCE_NAME \
    --zone=$ZONE \
    --machine-type=$MACHINE_TYPE \
    --subnet=$SUBNET_NAME \
    --network-tier=PREMIUM \
    --metadata-from-file startup-script=gcp_openvpn_startup.sh \
    --tags=openvpn,http-server,https-server \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --boot-disk-size=10GB \
    --boot-disk-type=pd-standard \
    --boot-disk-device-name=$INSTANCE_NAME

# 获取实例外部IP
EXTERNAL_IP=$(gcloud compute instances describe $INSTANCE_NAME \
    --zone=$ZONE \
    --format='get(networkInterfaces[0].accessConfigs[0].natIP)')

echo "OpenVPN服务器部署完成!"
echo "服务器公共IP: $EXTERNAL_IP"
echo "使用以下命令连接到服务器:"
echo "gcloud compute ssh $INSTANCE_NAME --zone=$ZONE"
echo "OpenVPN配置将在约5-10分钟后完成"
echo "完成后,您可以使用SCP下载客户端配置文件:"
echo "gcloud compute scp $INSTANCE_NAME:/home/$(whoami)/client.ovpn . --zone=$ZONE"

启动脚本 gcp_openvpn_startup.sh

#!/bin/bash

# 更新系统并安装依赖
apt-get update
apt-get install -y openvpn easy-rsa iptables-persistent net-tools

# 设置Easy-RSA
mkdir -p /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa

# 初始化PKI
./easyrsa init-pki

# 创建CA(无需交互)
EASYRSA_BATCH=1 ./easyrsa build-ca nopass

# 创建服务器证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass

# 创建Diffie-Hellman参数
./easyrsa gen-dh

# 创建TLS认证密钥
openvpn --genkey --secret /etc/openvpn/ta.key

# 创建客户端证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-client-full client nopass

# 配置OpenVPN服务器
cat > /etc/openvpn/server.conf << EOF
port 1194
proto udp
dev tun

ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
tls-auth /etc/openvpn/ta.key 0

server 172.16.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

keepalive 10 120
cipher AES-256-GCM
auth SHA256
compress lz4-v2
push "compress lz4-v2"

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3
EOF

# 创建日志目录
mkdir -p /var/log/openvpn

# 获取公共IP地址
PUBLIC_IP=$(curl -s https://api.ipify.org)

# 创建客户端配置
USERNAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/created-by" -H "Metadata-Flavor: Google" | cut -d'@' -f1)
if [ -z "$USERNAME" ]; then
    USERNAME="user"
fi

cat > /home/$USERNAME/client.ovpn << EOF
client
dev tun
proto udp
remote $PUBLIC_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
compress lz4-v2
verb 3

<ca>
$(cat /etc/openvpn/easy-rsa/pki/ca.crt)
</ca>

<cert>
$(cat /etc/openvpn/easy-rsa/pki/issued/client.crt)
</cert>

<key>
$(cat /etc/openvpn/easy-rsa/pki/private/client.key)
</key>

<tls-auth>
$(cat /etc/openvpn/ta.key)
</tls-auth>
key-direction 1
EOF

# 设置权限
chown $USERNAME:$USERNAME /home/$USERNAME/client.ovpn
chmod 600 /home/$USERNAME/client.ovpn

# 启用IP转发
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
sysctl -p /etc/sysctl.d/99-openvpn.conf

# 配置iptables
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE

# 保存iptables规则
netfilter-persistent save
netfilter-persistent reload

# 启动OpenVPN服务
systemctl enable openvpn@server
systemctl start openvpn@server

echo "OpenVPN服务器设置完成"

12.2.4 阿里云部署

使用阿里云CLI部署OpenVPN服务器:

#!/bin/bash
# aliyun_openvpn_deploy.sh

# 设置变量
REGION="cn-hangzhou"
VPC_NAME="openvpn-vpc"
VPC_CIDR="10.0.0.0/16"
VSWITCH_NAME="openvpn-vswitch"
VSWITCH_CIDR="10.0.1.0/24"
SECURITY_GROUP_NAME="openvpn-sg"
INSTANCE_NAME="openvpn-server"
INSTANCE_TYPE="ecs.t5-lc1m1.small"
IMAGE_ID="ubuntu_18_04_64_20G_alibase_20190624.vhd"
KEY_PAIR_NAME="openvpn-key"
VPN_NETWORK="172.16.0.0/24"

# 创建VPC
echo "创建VPC..."
VPC_ID=$(aliyun vpc CreateVpc \
    --RegionId $REGION \
    --VpcName $VPC_NAME \
    --CidrBlock $VPC_CIDR \
    --Description "VPC for OpenVPN server" \
    | jq -r '.VpcId')

echo "VPC创建完成: $VPC_ID"

# 等待VPC可用
sleep 5

# 创建交换机
echo "创建交换机..."
ZONE_ID=$(aliyun ecs DescribeZones \
    --RegionId $REGION \
    | jq -r '.Zones.Zone[0].ZoneId')

VSWITCH_ID=$(aliyun vpc CreateVSwitch \
    --RegionId $REGION \
    --VpcId $VPC_ID \
    --ZoneId $ZONE_ID \
    --VSwitchName $VSWITCH_NAME \
    --CidrBlock $VSWITCH_CIDR \
    --Description "VSwitch for OpenVPN server" \
    | jq -r '.VSwitchId')

echo "交换机创建完成: $VSWITCH_ID"

# 创建安全组
echo "创建安全组..."
SECURITY_GROUP_ID=$(aliyun ecs CreateSecurityGroup \
    --RegionId $REGION \
    --VpcId $VPC_ID \
    --SecurityGroupName $SECURITY_GROUP_NAME \
    --Description "Security group for OpenVPN server" \
    | jq -r '.SecurityGroupId')

echo "安全组创建完成: $SECURITY_GROUP_ID"

# 添加安全组规则
aliyun ecs AuthorizeSecurityGroup \
    --RegionId $REGION \
    --SecurityGroupId $SECURITY_GROUP_ID \
    --IpProtocol tcp \
    --PortRange 22/22 \
    --SourceCidrIp 0.0.0.0/0 \
    --Priority 1

aliyun ecs AuthorizeSecurityGroup \
    --RegionId $REGION \
    --SecurityGroupId $SECURITY_GROUP_ID \
    --IpProtocol udp \
    --PortRange 1194/1194 \
    --SourceCidrIp 0.0.0.0/0 \
    --Priority 1

aliyun ecs AuthorizeSecurityGroup \
    --RegionId $REGION \
    --SecurityGroupId $SECURITY_GROUP_ID \
    --IpProtocol tcp \
    --PortRange 443/443 \
    --SourceCidrIp 0.0.0.0/0 \
    --Priority 1

# 创建密钥对
echo "创建密钥对..."
aliyun ecs CreateKeyPair \
    --RegionId $REGION \
    --KeyPairName $KEY_PAIR_NAME \
    > $KEY_PAIR_NAME.json

# 保存私钥
jq -r '.PrivateKeyBody' $KEY_PAIR_NAME.json > $KEY_PAIR_NAME.pem
chmod 400 $KEY_PAIR_NAME.pem

# 创建ECS实例
echo "创建ECS实例..."
INSTANCE_ID=$(aliyun ecs CreateInstance \
    --RegionId $REGION \
    --ZoneId $ZONE_ID \
    --ImageId $IMAGE_ID \
    --InstanceType $INSTANCE_TYPE \
    --InstanceName $INSTANCE_NAME \
    --SecurityGroupId $SECURITY_GROUP_ID \
    --VSwitchId $VSWITCH_ID \
    --KeyPairName $KEY_PAIR_NAME \
    --SystemDiskCategory cloud_efficiency \
    --SystemDiskSize 40 \
    --InstanceChargeType PostPaid \
    --UserData $(base64 -w 0 aliyun_openvpn_userdata.sh) \
    | jq -r '.InstanceId')

echo "ECS实例创建完成: $INSTANCE_ID"

# 分配公网IP
echo "分配公网IP..."
PUBLIC_IP=$(aliyun ecs AllocatePublicIpAddress \
    --RegionId $REGION \
    --InstanceId $INSTANCE_ID \
    | jq -r '.IpAddress')

echo "公网IP分配完成: $PUBLIC_IP"

# 启动实例
echo "启动实例..."
aliyun ecs StartInstance \
    --RegionId $REGION \
    --InstanceId $INSTANCE_ID

echo "OpenVPN服务器部署完成!"
echo "服务器公共IP: $PUBLIC_IP"
echo "使用以下命令连接到服务器:"
echo "ssh -i $KEY_PAIR_NAME.pem root@$PUBLIC_IP"
echo "OpenVPN配置将在约5-10分钟后完成"
echo "完成后,您可以使用SCP下载客户端配置文件:"
echo "scp -i $KEY_PAIR_NAME.pem root@$PUBLIC_IP:/root/client.ovpn ."

用户数据脚本 aliyun_openvpn_userdata.sh

#!/bin/bash

# 更新系统并安装依赖
apt-get update
apt-get install -y openvpn easy-rsa iptables-persistent net-tools

# 设置Easy-RSA
mkdir -p /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa

# 初始化PKI
./easyrsa init-pki

# 创建CA(无需交互)
EASYRSA_BATCH=1 ./easyrsa build-ca nopass

# 创建服务器证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass

# 创建Diffie-Hellman参数
./easyrsa gen-dh

# 创建TLS认证密钥
openvpn --genkey --secret /etc/openvpn/ta.key

# 创建客户端证书和密钥
EASYRSA_BATCH=1 ./easyrsa build-client-full client nopass

# 配置OpenVPN服务器
cat > /etc/openvpn/server.conf << EOF
port 1194
proto udp
dev tun

ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
tls-auth /etc/openvpn/ta.key 0

server 172.16.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

keepalive 10 120
cipher AES-256-GCM
auth SHA256
compress lz4-v2
push "compress lz4-v2"

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3
EOF

# 创建日志目录
mkdir -p /var/log/openvpn

# 获取公共IP地址
PUBLIC_IP=$(curl -s https://api.ipify.org)

# 创建客户端配置
cat > /root/client.ovpn << EOF
client
dev tun
proto udp
remote $PUBLIC_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
compress lz4-v2
verb 3

<ca>
$(cat /etc/openvpn/easy-rsa/pki/ca.crt)
</ca>

<cert>
$(cat /etc/openvpn/easy-rsa/pki/issued/client.crt)
</cert>

<key>
$(cat /etc/openvpn/easy-rsa/pki/private/client.key)
</key>

<tls-auth>
$(cat /etc/openvpn/ta.key)
</tls-auth>
key-direction 1
EOF

# 设置权限
chmod 600 /root/client.ovpn

# 启用IP转发
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
sysctl -p /etc/sysctl.d/99-openvpn.conf

# 配置iptables
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE

# 保存iptables规则
netfilter-persistent save
netfilter-persistent reload

# 启动OpenVPN服务
systemctl enable openvpn@server
systemctl start openvpn@server

echo "OpenVPN服务器设置完成"

12.3 混合云网络架构

12.3.1 站点到云VPN

以下是使用OpenVPN连接本地数据中心与AWS VPC的配置示例:

#!/bin/bash
# site_to_cloud_vpn.sh

# 设置变量
LOCAL_NETWORK="192.168.0.0/24"  # 本地网络CIDR
CLOUD_NETWORK="10.0.0.0/16"     # 云端VPC CIDR
CLOUD_VPN_IP="54.123.45.67"     # 云端OpenVPN服务器公共IP
LOCAL_VPN_IP="203.0.113.10"     # 本地OpenVPN服务器公共IP

# 本地OpenVPN服务器配置
cat > /etc/openvpn/server.conf << EOF
port 1194
proto udp
dev tun

ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/server.crt
key /etc/openvpn/pki/private/server.key
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key 0

server 172.16.0.0 255.255.255.0

# 路由配置 - 将云端网络流量路由到VPN
push "route $CLOUD_NETWORK 255.255.255.0"

# 不将所有流量重定向到VPN,只路由特定网络
;push "redirect-gateway def1 bypass-dhcp"

keepalive 10 120
cipher AES-256-GCM
auth SHA256
compress lz4-v2
push "compress lz4-v2"

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3

# 允许客户端之间通信
client-to-client

# 保持连接,即使没有客户端
keepalive 10 60
EOF

# 创建云端OpenVPN客户端配置
cat > /etc/openvpn/cloud_client.conf << EOF
client
dev tun
proto udp
remote $CLOUD_VPN_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
compress lz4-v2
verb 3

# 添加本地网络路由到云端
route $LOCAL_NETWORK 255.255.255.0

<ca>
# 粘贴云端CA证书
</ca>

<cert>
# 粘贴云端客户端证书
</cert>

<key>
# 粘贴云端客户端密钥
</key>

<tls-auth>
# 粘贴云端TLS密钥
</tls-auth>
key-direction 1
EOF

# 启用IP转发
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
sysctl -p /etc/sysctl.d/99-openvpn.conf

# 配置iptables以允许VPN流量通过
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o eth0 -s 172.16.0.0/24 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 172.16.0.0/24 -j ACCEPT

# 保存iptables规则
netfilter-persistent save
netfilter-persistent reload

# 启动OpenVPN服务器和客户端
systemctl enable openvpn@server
systemctl start openvpn@server
systemctl enable openvpn@cloud_client
systemctl start openvpn@cloud_client

echo "站点到云VPN配置完成"

12.3.2 多云连接

以下是使用OpenVPN连接多个云平台的配置示例:

”`python #!/usr/bin/env python3

multi_cloud_vpn_manager.py

import os import sys import subprocess import argparse import yaml import time

class MultiCloudVPNManager: def init(self, config_file): self.config_file = config_file self.load_config() self.openvpn_base_dir = “/etc/openvpn” self.ensure_directories()

def load_config(self):
    try:
        with open(self.config_file, 'r') as f:
            self.config = yaml.safe_load(f)
    except Exception as e:
        print(f"Error loading configuration: {e}")
        sys.exit(1)

def ensure_directories(self):
    os.makedirs(f"{self.openvpn_base_dir}/ccd", exist_ok=True)
    os.makedirs(f"{self.openvpn_base_dir}/keys", exist_ok=True)
    os.makedirs(f"{self.openvpn_base_dir}/clients", exist_ok=True)

def setup_hub_server(self):
    """设置中心OpenVPN服务器"""
    hub_config = self.config.get('hub', {})
    if not hub_config:
        print("Error: Hub configuration missing")
        return False

    # 创建服务器配置
    server_conf = f"""\

port {hub_config.get(‘port’, 1194)}
proto {hub_config.get(‘protocol’, ‘udp’)}
dev tun


ca {self.openvpn_base_dir}/keys/ca.crt
cert {self.openvpn_base_dir}/keys/server.crt
key {self.openvpn_base_dir}/keys/server.key
dh {self.openvpn_base_dir}/keys/dh.pem
tls-auth {self.openvpn_base_dir}/keys/ta.key 0


server {hub_config.get(‘vpn_network’, ‘10.8.0.0’)} {hub_config.get(‘vpn_netmask’, ‘255.255.255.0’)}


keepalive 10 120
cipher AES-256-GCM
auth SHA256
compress lz4-v2
push “compress lz4-v2”


user nobody
group nogroup


persist-key
persist-tun


status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3

允许客户端之间通信


client-to-client

使用客户端配置目录


client-config-dir {self.openvpn_base_dir}/ccd
”“”

    # 添加路由推送配置
    for cloud in self.config.get('clouds', []):
        network = cloud.get('network')
        if network:
            server_conf += f"push \"route {network}\"\n"

    # 写入服务器配置文件
    with open(f"{self.openvpn_base_dir}/server.conf", 'w') as f:
        f.write(server_conf)

    print("Hub server configuration created")
    return True

def setup_cloud_clients(self):
    """为每个云平台设置客户端配置"""
    for cloud in self.config.get('clouds', []):
        cloud_name = cloud.get('name')
        if not cloud_name:
            print("Warning: Cloud without name found, skipping")
            continue

        # 创建客户端配置
        client_conf = f"""\

client
dev tun
proto {cloud.get(‘protocol’, ‘udp’)}
remote {cloud.get(‘vpn_server’)} {cloud.get(‘port’, 1194)}
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
compress lz4-v2
verb 3

添加路由


”“”

        # 添加本地网络路由
        local_network = self.config.get('hub', {}).get('local_network')
        if local_network:
            client_conf += f"route {local_network}\n"

        # 添加其他云网络路由
        for other_cloud in self.config.get('clouds', []):
            if other_cloud.get('name') != cloud_name and other_cloud.get('network'):
                client_conf += f"route {other_cloud.get('network')}\n"

        # 添加证书和密钥占位符
        client_conf += """\

CA certificate placeholder



Client certificate placeholder



Client key placeholder



TLS key placeholder



key-direction 1
”“”

        # 写入客户端配置文件
        with open(f"{self.openvpn_base_dir}/clients/{cloud_name}.conf", 'w') as f:
            f.write(client_conf)

        # 创建CCD文件以设置固定IP和路由
        with open(f"{self.openvpn_base_dir}/ccd/{cloud_name}", 'w') as f:
            if cloud.get('fixed_ip'):
                f.write(f"ifconfig-push {cloud.get('fixed_ip')} {self.config.get('hub', {}).get('vpn_netmask', '255.255.255.0')}\n")
            if cloud.get('network'):
                f.write(f"iroute {cloud.get('network')}\n")

        print(f"Client configuration for {cloud_name} created")

    return True

def setup_iptables(self):
    """配置iptables规则"""
    try:
        # 启用IP转发
        with open("/etc/sysctl.d/99-openvpn.conf", 'w') as f:
            f.write("net.ipv4.ip_forward = 1\n")
        subprocess.run(["sysctl", "-p", "/etc/sysctl.d/99-openvpn.conf"], check=True)

        # 配置NAT
        vpn_network = self.config.get('hub', {}).get('vpn_network', '10.8.0.0/24')
        subprocess.run(["iptables", "-t", "nat", "-A", "POSTROUTING", "-s", vpn_network, "-o", "eth0", "-j", "MASQUERADE"], check=True)

        # 允许转发
        subprocess.run(["iptables", "-A", "FORWARD", "-i", "tun+", "-j", "ACCEPT"], check=True)
        subprocess.run(["iptables", "-A", "FORWARD", "-o", "tun+", "-j", "ACCEPT"], check=True)

        # 保存规则
        subprocess.run(["netfilter-persistent", "save"], check=True)

        print("iptables rules configured")
        return True
    except subprocess.SubprocessError as e:
        print(f"Error configuring iptables: {e}")
        return False