在之前的文章中,我们介绍了如何在Ubuntu系统中自动创建用于OpenVPN的SSL证书脚本。证书创建完成之后,OpenVPN的配置工作其实已经完成了一大半。

同时,我们也介绍过在Ubuntu系统手工配置OpenVPN服务端和客户端连接的方法。今天,我们的目标就是将手工配置服务端的过程完全自动化。
与在CentOS系统中的思路一致,证书创建完成后,服务端剩余的配置主要包括创建server.conf配置文件,以及替换默认的openvpn.service服务文件。由于openvpn.service需要引用server.conf,所以我们先来生成server.conf。
server.conf需要引用之前生成的ca.crt、ttserver.crt、ttserver.key和dh.pem这四个文件。因此,我们首先需要调整证书的存放路径,将相关文件复制到OpenVPN的服务端配置目录。可以添加以下四条命令:
cp /usr/share/easy-rsa/pki/ca.crt /etc/openvpn/server/ca.crt
cp /usr/share/easy-rsa/pki/dh.pem /etc/openvpn/server/dh.pem
cp /usr/share/easy-rsa/pki/issued/ttserver.crt /etc/openvpn/server/ttserver.crt
cp /usr/share/easy-rsa/pki/private/ttserver.key /etc/openvpn/server/ttserver.key
OpenVPN软件通常系统已经自带,但为了脚本的可移植性和潜在的升级需求,我们可以显式执行安装命令:
apt install -y openvpn
如果将其转换为Shell脚本中的函数,可以这样写:
# 安装openVPN
install_openvpn() {
echo "正在安装openVPN..."
apt -y install openvpn
echo "openVPN安装完成。"
}
接下来,我们就可以直接创建并写入server.conf配置文件的内容了。
# 配置/etc/openvpn/server/server.conf
configure_server_conf(){
cat<< EOF > /etc/openvpn/server/server.conf
local 0.0.0.0
proto tcp
port 44331
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/ttserver.crt
key /etc/openvpn/server/ttserver.key
dh /etc/openvpn/server/dh.pem
topology subnet
server 10.153.117.0 255.255.255.0
push "dhcp-option DNS 8.8.8.8"
push "redirect-gateway def1 bypass-dhcp"
duplicate-cn
keepalive 20 120
persist-key
persist-tun
EOF
# 检查配置文件是否写入成功
echo "server.conf配置如下:"
cat /etc/openvpn/server/server.conf
}
紧接着是OpenVPN的服务配置文件openvpn.service,同样采用直接写入内容的方式。
# 配置/usr/lib/systemd/system/openvpn.service
configure_openvpn_service() {
rm -f /usr/lib/systemd/system/openvpn.service
cat << EOF > /usr/lib/systemd/system/openvpn.service
[Unit]
Description=OpenVPN Server
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/server/server.conf
EOF
# 检查配置文件是否写入成功
echo "openvpn.service配置如下:"
cat /usr/lib/systemd/system/openvpn.service
}
配置文件就绪后,我们需要重新加载systemd配置并启动OpenVPN服务。这个过程涉及服务管理、状态检查以及关键的网络/系统层转发规则设置。
# 启动openVPN服务
start_openvpn(){
systemctl daemon-reload
systemctl start openvpn
systemctl enable openvpn
systemctl restart openvpn
echo “openVPN服务状态如下:”
systemctl status openvpn
ss -atnp |grep 44331
ss -atnp |grep openvpn
echo “使能本地转发功能!”
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -j MASQUERADE
}
服务端配置完成后,我们通常还需要为客户端生成一份配置文件。为了简化客户端部署,我们可以生成一个集成了所有证书和密钥的.ovpn文件。
这个文件需要包含ca.crt、ttclient.crt和ttclient.key的内容,以及服务器的公网IP地址。首先创建配置文件并写入固定的头部信息。
# 创建tietou.ovpn配置文件
create_ovpn() {
cat << EOF > /etc/openvpn/client/tietou.ovpn
client
dev tun
proto tcp
nobind
resolv-retry infinite
persist-key
persist-tun
EOF
}
然后,通过调用外部API获取服务器的公网IP并写入配置。
# 获取IP地址
get_ip() {
IP=$(curl -s cip.cc | awk ‘/IP/{print $3}‘)
echo “公网IP地址为:$IP”
# 写入到配置文件中
echo “remote $IP 44331” >> /etc/openvpn/client/tietou.ovpn
}
接着,将CA证书、客户端证书和私钥的内容提取并嵌入到配置文件中。
# 提取ca.crt的证书内容
get_cacrt() {
CACRT=$(awk ‘/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/‘ /usr/share/easy-rsa/pki/ca.crt)
# 将证书内容写入到配置文件中
echo “<ca>” >> /etc/openvpn/client/tietou.ovpn
echo “$CACRT” >> /etc/openvpn/client/tietou.ovpn
echo “</ca>” >> /etc/openvpn/client/tietou.ovpn
}
# 提取ttclient.crt的证书内容
get_clientcrt() {
CLIENTCRT=$(awk ‘/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/‘ /usr/share/easy-rsa/pki/issued/ttclient.crt)
# 将证书内容写入到配置文件中
echo “<cert>” >> /etc/openvpn/client/tietou.ovpn
echo “$CLIENTCRT” >> /etc/openvpn/client/tietou.ovpn
echo “</cert>” >> /etc/openvpn/client/tietou.ovpn
}
# 提取ttclient.key的证书内容
get_clientkey() {
CLIENTKEY=$(awk ‘/-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----/‘ /usr/share/easy-rsa/pki/private/ttclient.key)
# 将证书内容写入到配置文件中
echo “<key>” >> /etc/openvpn/client/tietou.ovpn
echo “$CLIENTKEY” >> /etc/openvpn/client/tietou.ovpn
echo “</key>” >> /etc/openvpn/client/tietou.ovpn
}
# 展示tietou.ovpn配置内容
echo “tietou.ovpn配置内容如下:”
cat /etc/openvpn/client/tietou.ovpn
最终脚本
最后,我们将之前所有独立的函数模块组合起来,形成一个完整的一键部署脚本。这个脚本从安装依赖、生成证书,到配置服务、启动服务并生成客户端配置,实现了全流程自动化。
#!/bin/bash
# 安装Easy-RSA
install_easyrsa() {
echo "正在安装Easy-RSA..."
apt install -y easy-rsa
echo "Easy-RSA安装完成。"
}
# 初始化Easy-RSA环境
init_easyrsa() {
echo "初始化Easy-RSA环境..."
cd /usr/share/easy-rsa/
# 备份vars.example为vars,避免覆盖
if [ -f vars ]; then
mv vars vars.backup
fi
cp vars.example vars
echo "Easy-RSA环境初始化完成。"
}
# 更新vars文件中的机构信息字段
update_vars() {
echo "更新vars文件中的机构信息字段..."
cd /usr/share/easy-rsa/
# 向vars文件中插入机构信息字段
echo ‘set_var EASYRSA_REQ_COUNTRY "CN"‘ >> vars
echo ‘set_var EASYRSA_REQ_PROVINCE "Beijing"‘ >> vars
echo ‘set_var EASYRSA_REQ_CITY "Haidian"‘ >> vars
echo ‘set_var EASYRSA_REQ_ORG "TIETOU_TECH"‘ >> vars
echo ‘set_var EASYRSA_REQ_EMAIL "tietou@h3cadmin.cn"‘ >> vars
echo ‘set_var EASYRSA_REQ_OU "Tietou_openVPN"‘ >> vars
echo "vars文件中的机构信息字段已更新。"
}
# 生成证书和密钥
generate_certs() {
echo "正在生成证书和密钥..."
cd /usr/share/easy-rsa/
# 初始化PKI目录结构
./easyrsa init-pki
# 清空证书目录
echo "yes" | ./easyrsa clean-all
# 生成证书和密钥文件
echo | ./easyrsa build-ca nopass
echo | ./easyrsa gen-req ttserver nopass
echo "yes" | ./easyrsa sign server ttserver
./easyrsa gen-dh
echo | ./easyrsa gen-req ttclient nopass
echo "yes" | ./easyrsa sign-req client ttclient
echo "证书和密钥生成完成。"
}
# 安装openVPN
install_openvpn() {
echo "正在安装openVPN..."
apt -y install openvpn
echo "openVPN安装完成。"
}
# 配置/etc/openvpn/server/server.conf
configure_server_conf() {
cp /usr/share/easy-rsa/pki/ca.crt /etc/openvpn/server/ca.crt
cp /usr/share/easy-rsa/pki/dh.pem /etc/openvpn/server/dh.pem
cp /usr/share/easy-rsa/pki/issued/ttserver.crt /etc/openvpn/server/ttserver.crt
cp /usr/share/easy-rsa/pki/private/ttserver.key /etc/openvpn/server/ttserver.key
cat << EOF > /etc/openvpn/server/server.conf
local 0.0.0.0
proto tcp
port 44331
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/ttserver.crt
key /etc/openvpn/server/ttserver.key
dh /etc/openvpn/server/dh.pem
topology subnet
server 10.153.117.0 255.255.255.0
push "dhcp-option DNS 8.8.8.8"
push "redirect-gateway def1 bypass-dhcp"
duplicate-cn
keepalive 20 120
persist-key
persist-tun
EOF
# 检查配置文件是否写入成功
echo "server.conf配置如下:"
cat /etc/openvpn/server/server.conf
}
# 配置/usr/lib/systemd/system/openvpn.service
configure_openvpn_service() {
rm -f /usr/lib/systemd/system/openvpn.service
cat << EOF > /usr/lib/systemd/system/openvpn.service
[Unit]
Description=OpenVPN Server
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/server/server.conf
EOF
# 检查配置文件是否写入成功
echo "openvpn.service配置如下:"
cat /usr/lib/systemd/system/openvpn.service
}
# 启动openVPN服务
start_openvpn() {
systemctl daemon-reload
systemctl start openvpn
systemctl enable openvpn
systemctl restart openvpn
echo "openVPN服务状态如下:"
systemctl status openvpn
ss -atnp |grep 44331
ss -atnp |grep openvpn
echo "使能本地转发功能!"
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -j MASQUERADE
}
# 创建tietou.ovpn配置文件
create_ovpn() {
cat << EOF > /etc/openvpn/client/tietou.ovpn
client
dev tun
proto tcp
nobind
resolv-retry infinite
persist-key
persist-tun
EOF
}
# 获取IP地址
get_ip() {
IP=$(curl -s cip.cc | awk ‘/IP/{print $3}‘)
echo "公网IP地址为:$IP"
# 写入到配置文件中
echo "remote $IP 44331" >> /etc/openvpn/client/tietou.ovpn
}
# 提取ca.crt的证书内容
get_cacrt() {
CACRT=$(awk ‘/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/‘ /usr/share/easy-rsa/pki/ca.crt)
# 将证书内容写入到配置文件中
echo "<ca>" >> /etc/openvpn/client/tietou.ovpn
echo "$CACRT" >> /etc/openvpn/client/tietou.ovpn
echo "</ca>" >> /etc/openvpn/client/tietou.ovpn
}
# 提取ttclient.crt的证书内容
get_clientcrt() {
CLIENTCRT=$(awk ‘/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/‘ /usr/share/easy-rsa/pki/issued/ttclient.crt)
echo "<cert>" >> /etc/openvpn/client/tietou.ovpn
echo "$CLIENTCRT" >> /etc/openvpn/client/tietou.ovpn
echo "</cert>" >> /etc/openvpn/client/tietou.ovpn
}
# 提取ttclient.key的证书内容
get_clientkey() {
CLIENTKEY=$(awk ‘/-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----/‘ /usr/share/easy-rsa/pki/private/ttclient.key)
# 将证书内容写入到配置文件中
echo "<key>" >> /etc/openvpn/client/tietou.ovpn
echo "$CLIENTKEY" >> /etc/openvpn/client/tietou.ovpn
echo "</key>" >> /etc/openvpn/client/tietou.ovpn
}
# 创建SSL-cert目录
generate_dir() {
# 获取当前时间
current_time=$(date +"%Y%m%d%H%M")
# 创建新的目录
new_dir="/SSL-cert/${current_time}"
mkdir -p "${new_dir}"
# 将证书和密钥复制到新目录下
cp /usr/share/easy-rsa/pki/ca.crt "${new_dir}/ca.crt"
cp /usr/share/easy-rsa/pki/issued/ttserver.crt "${new_dir}/ttserver.crt"
cp /usr/share/easy-rsa/pki/private/ttserver.key "${new_dir}/ttserver.key"
cp /usr/share/easy-rsa/pki/issued/ttclient.crt "${new_dir}/ttclient.crt"
cp /usr/share/easy-rsa/pki/private/ttclient.key "${new_dir}/ttclient.key"
echo "证书和密钥已复制到目录:${new_dir}"
}
# 主函数
main() {
install_easyrsa
init_easyrsa
update_vars
generate_certs
install_openvpn
configure_server_conf
configure_openvpn_service
start_openvpn
create_ovpn
get_ip
get_cacrt
get_clientcrt
get_clientkey
generate_dir
}
main;
# 展示tietou.ovpn配置内容
echo "tietou.ovpn配置内容如下:"
cat /etc/openvpn/client/tietou.ovpn
现在,运行这个整合后的脚本试试看。整个过程通常在一分钟之内即可完成。

接下来,在客户端使用导入文件的方式导入生成的tietou.ovpn配置文件,并发起VPN拨号连接。

拨号成功后,测试一下网络连通性。

测试结果显示一切顺利,自动化脚本部署成功!这种将复杂配置流程脚本化的方法,非常适合需要快速、重复部署网络服务的运维场景。如果你想了解更多关于网络自动化或脚本编写的实践,欢迎到云栈社区与更多开发者交流探讨。