技术文档收录
ASCII
Tcpdump
IPV4保留地址段
深入理解以太网网线原理 - 三帛的世界
Linux
WireGuard 一键安装脚本 | 秋水逸冰
SSH Config 那些你所知道和不知道的事 | Deepzz's Blog
Linux 让终端走代理的几种方法
ubuntu 20.04 server 版设置静态 IP 地址 - 链滴
Linux 挂载 Windows 共享磁盘的方法 - 技术学堂
将 SMB/CIFS 网络硬盘永久的挂载到 Ubuntu 上 - 简书
linux 获取当前脚本的绝对路径 | aimuke
[Linux] Linux 使用 / dev/urandom 生成随机数 - piaohua's blog
Linux 生成随机数的多种方法 | Just Do It
Linux 的 Centos7 版本下忘记 root 或者普通用户密码怎么办?
Git 强制拉取覆盖本地
SSH 安全加固指南 - FreeBuf 网络安全行业门户
Linux 系统安全强化指南 - FreeBuf 网络安全行业门户
Linux 入侵排查 - FreeBuf 网络安全行业门户
sshd_config 配置详解 - 简书
SSH 权限详解 - SegmentFault 思否
CentOS 安装 node.js 环境 - SegmentFault 思否
如何在 CentOS 7 上安装 Node.js 和 npm | myfreax
几款 ping tcping 工具总结
OpenVpn 搭建教程 | Jesse's home
openvpn 一键安装脚本 - 那片云
OpenVPN 解决 每小时断线一次 - 爱开源
OpenVPN 路由设置 – 凤曦的小窝
OpenVPN 设置非全局代理 - 镜子的记录簿
TinyProxy 使用帮助 - 简书
Ubuntu 下使用 TinyProxy 搭建代理 HTTP 服务器_Linux_运维开发网_运维开发技术经验分享
Linux 软件包管理工具 Snap 常用命令 - 简书
linux systemd 参数详解
Systemd 入门教程:命令篇 - 阮一峰的网络日志
记一次 Linux 木马清除过程
rtty:在任何地方通过 Web 访问您的终端
02 . Ansible 高级用法 (运维开发篇)
终于搞懂了服务器为啥产生大量的 TIME_WAIT!
巧妙的 Linux 命令,再来 6 个!
77% 的 Linux 运维都不懂的内核问题,这篇全告诉你了
运维工程师必备:请收好 Linux 网络命令集锦
一份阿里员工的 Java 问题排查工具单
肝了 15000 字性能调优系列专题(JVM、MySQL、Nginx and Tomcat),看不完先收
作业调度算法(FCFS,SJF,优先级调度,时间片轮转,多级反馈队列) | The Blog Of WaiterXiaoYY
看了这篇还不会 Linux 性能分析和优化,你来打我
2019 运维技能风向标
更安全的 rm 命令,保护重要数据
求你了,别再纠结线程池大小了!
Linux sudo 详解 | 失落的乐章
重启大法好!线上常见问题排查手册
sudo 使用 - 笨鸟教程的博客 | BY BenderFly
shell 在手分析服务器日志不愁? - SegmentFault 思否
sudo 与 visudo 的超细用法说明_陈发哥 007 的技术博客_51CTO 博客
ESXI 下无损扩展 Linux 硬盘空间 | Naonao Blog
Linux 学习记录:su 和 sudo | Juntao Tan 的个人博客
使用者身份切换 | Linux 系统教程(笔记)
你会使用 Linux 编辑器 vim 吗?
在 Windows、Linux 和 Mac 上查看 Wi-Fi 密码
linux 隐藏你的 crontab 后门 - 简书
Linux 定时任务详解 - Tr0y's Blog
linux 的 TCP 连接数量最大不能超过 65535 个吗,那服务器是如何应对百万千万的并发的?_一口 Linux 的博客 - CSDN 博客_tcp 连接数多少正常
万字长文 + 28 张图,一次性说清楚 TCP,运维必藏
为什么 p2p 模式的 tunnel 底层通常用 udp 而不是 tcp?
记一次服务器被入侵挖矿 - tlanyan
shell 判断一个变量是否为空方法总结 - 腾讯云开发者社区 - 腾讯云
系统安装包管理工具 | Escape
编译代码时动态地链接库 - 51CTO.COM
甲骨文 Oracle Cloud 添加新端口开放的方法 - WirelessLink 社区
腾讯云 Ubuntu 添加 swap 分区的方法_弓弧名家_玄真君的博客 - CSDN 博客
Oracle 开放全部端口并关闭防火墙 - 清~ 幽殇
谁再说不熟悉 Linux 命令, 就把这个给他扔过去!
即插即用,运维工程师必会正则表达式大全
Shell脚本编写及常见面试题
Samba 文件共享服务器
到底一台服务器上最多能创建多少个 TCP 连接 | plantegg
SSH 密钥登录 - SSH 教程 - 网道
在 Bash 中进行 encodeURIComponent/decodeURIComponent | Harttle Land
使用 Shell 脚本来处理 JSON - Tom CzHen's Blog
Docker
「Docker」 - 保存镜像 - 知乎
终于可以像使用 Docker 一样丝滑地使用 Containerd 了!
私有镜像仓库选型:Harbor VS Quay - 乐金明的博客 | Robin Blog
exec 与 entrypoint 使用脚本 | Mr.Cheng
Dockerfile 中的 CMD 与 ENTRYPOINT
使用 Docker 配置 MySQL 主从数据库 - 墨天轮
Alpine vs Distroless vs Busybox – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
再见,Docker!
docker save 与 docker export 的区别 - jingsam
如何优雅的关闭容器
docker 储存之 tmpfs 、bind-mounts、volume | 陌小路的个人博客
Dockerfile 中 VOLUME 与 docker -v 的区别是什么 - 开发技术 - 亿速云
理解 docker 容器的退出码 | Vermouth | 博客 | docker | k8s | python | go | 开发
【Docker 那些事儿】容器监控系统,来自 Docker 的暴击_飞向星的客机的博客 - CSDN 博客
【云原生】Docker 镜像详细讲解_微枫 Micromaple 的博客 - CSDN 博客_registry-mirrors
【云原生】Helm 架构和基础语法详解
CMD 和 Entrypoint 命令使用变量的用法
实时查看容器日志 - 苏洋博客
Traefik 2 使用指南,愉悦的开发体验 - 苏洋博客
为你的 Python 应用选择一个最好的 Docker 映像 | 亚马逊 AWS 官方博客
【云原生】镜像构建实战操作(Dockerfile)
Docker Compose 中的 links 和 depends_on 的区别 - 编程知识 - 白鹭情
Python
Pipenv:新一代Python项目环境与依赖管理工具 - 知乎
Python list 列表实现栈和队列
Python 各种排序 | Lesley's blog
Python 中使用 dateutil 模块解析时间 - SegmentFault 思否
一个小破网站,居然比 Python 官网还牛逼
Python 打包 exe 的王炸 - Nuitka
Django - - 基础 - - Django ORM 常用查询语法及进阶
[Python] 小知識:== 和 is 的差異 - Clay-Technology World
Window
批处理中分割字符串 | 网络进行时
Windows 批处理基础命令学习 - 简书
在Windows上设置WireGuard
Windows LTSC、LTSB、Server 安装 Windows Store 应用商店
windows 重启 rdpclip.exe 的脚本
中间件
Nginx 中的 Rewrite 的重定向配置与实践
RabbitMQ 的监控
RabbitMq 最全的性能调优笔记 - SegmentFault 思否
为什么不建议生产用 Redis 主从模式?
高性能消息中间件——NATS
详解:Nginx 反代实现 Kibana 登录认证功能
分布式系统关注点:仅需这一篇,吃透 “负载均衡” 妥妥的
仅需这一篇,妥妥的吃透” 负载均衡”
基于 nginx 实现上游服务器动态自动上下线——不需 reload
Nginx 学习书单整理
最常见的日志收集架构(ELK Stack)
分布式之 elk 日志架构的演进
CAT 3.0 开源发布,支持多语言客户端及多项性能提升
Kafka 如何做到 1 秒处理 1500 万条消息?
Grafana 与 Kibana
ELK 日志系统之通用应用程序日志接入方案
ELK 简易 Nginx 日志系统搭建: ElasticSearch+Kibana+Filebeat
记一次 Redis 连接池问题引发的 RST
把 Redis 当作队列来用,你好大的胆子……
Redis 最佳实践:业务层面和运维层面优化
Redis 为什么变慢了?常见延迟问题定位与分析
好饭不怕晚,扒一下 Redis 配置文件的底 Ku
rabbitmq 集群搭建以及万级并发下的性能调优
别再问我 Redis 内存满了该怎么办了
Nginx 状态监控及日志分析
uWSGI 的安装及配置详解
uwsgi 异常服务器内存 cpu 爆满优化思路
Uwsgi 内存占用过多 - 简书
Nginx 的 limit 模块
Nginx 内置模块简介
Redis 忽然变慢了如何排查并解决?_redis_码哥字节_InfoQ 写作社区
领导:谁再用 redis 过期监听实现关闭订单,立马滚蛋!
Nginx 限制 IP 访问频率以及白名单配置_问轩博客
Nginx $remote_addr 和 $proxy_add_x_forwarded_for 变量详解
Caddy 部署实践
一文搞定 Nginx 限流
数据库
SqlServer 将数据库中的表复制到另一个数据库_MsSql_脚本之家
SQL Server 数据库同步,订阅、发布、复制、跨服务器
sql server 无法删除本地发布 | 辉克's Blog
SQLite全文检索
SQL 重复记录查询的几种方法 - 简书
SQL SERVER 使用订阅发布同步数据库(转)
Mysql 查看用户连接数配置及每个 IP 的请求情况 - 墨天轮
优化 SQL 的 21 条方案
SQL Server 连接时好时坏的奇怪问题
MS SQL 执行大脚本文件时,提示 “内存不足” 的解决办法 - 阿里云开发者社区
防火墙-iptables
iptables 常用规则:屏蔽 IP 地址、禁用 ping、协议设置、NAT 与转发、负载平衡、自定义链
防火墙 iptables 企业防火墙之 iptables
Linux 防火墙 ufw 简介
在 Ubuntu 中用 UFW 配置防火墙
在 Ubuntu20.04 上怎样使用 UFW 配置防火墙 - 技术库存网
监控类
开箱即用的 Prometheus 告警规则集
prometheus☞搭建 | zyh
docker 部署 Prometheus 监控服务器及容器并发送告警 | chris'wang
PromQL 常用命令 | LRF 成长记
prometheus 中使用 python 手写 webhook 完成告警
持续集成CI/CD
GitHub Actions 的应用场景 | 记录干杯
GithubActions · Mr.li's Blog
工具类
GitHub 中的开源网络广告杀手,十分钟快速提升网络性能
SSH-Auditor:一款 SHH 弱密码探测工具
别再找了,Github 热门开源富文本编辑器,最实用的都在这里了 - srcmini
我最喜欢的 CLI 工具
推荐几款 Redis 可视化工具
内网代理工具与检测方法研究
环境篇:数据同步工具 DataX
全能系统监控工具 dstat
常用 Web 安全扫描工具合集
给你一款利器!轻松生成 Nginx 配置文件
教程类
Centos7 搭建神器 openvpn | 运维随笔
搭建 umami 收集个人网站统计数据 | Reorx’s Forge
openvpn安装教程
基于 gitea+drone 完成小团队的 CI/CD - 德国粗茶淡饭
将颜色应用于交替行或列
VMware Workstation 全系列合集 精简安装注册版 支持 SLIC2.6、MSDM、OSX 更新 16.2.3_虚拟机讨论区_安全区 卡饭论坛 - 互助分享 - 大气谦和!
在 OpenVPN 上启用 AD+Google Authenticator 认证 | 运维烂笔头
Github 进行 fork 后如何与原仓库同步:重新 fork 很省事,但不如反复练习版本合并 · Issue #67 · selfteaching/the-craft-of-selfteaching
卧槽,VPN 又断开了!!- 阿里云开发者社区
Grafana Loki 学习之踩坑记
zerotier 的 planet 服务器(根服务器)的搭建踩坑记。无需 zerotier 官网账号。
阿里云 qcow2 镜像转 vmdk,导入 ESXi - 唐际忠的博客
Caddy 入门 – 又见杜梨树
【Caddy2】最新 Caddy2 配置文件解析 - Billyme 的博客
Web 服务器 Caddy 2 | Haven200
手把手教你打造高效的 Kubernetes 命令行终端
Keras 作者:给软件开发者的 33 条黄金法则
超详细的网络抓包神器 Tcpdump 使用指南
使用 fail2ban 和 FirewallD 黑名单保护你的系统
linux 下 mysql 数据库单向同步配置方法分享 (Mysql)
MySQL 快速删除大量数据(千万级别)的几种实践方案
GitHub 上的优质 Linux 开源项目,真滴牛逼!
WireGuard 教程:使用 Netmaker 来管理 WireGuard 的配置 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
Tailscale 基础教程:Headscale 的部署方法和使用教程 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
Nebula Graph 的 Ansible 实践
改进你的 Ansible 剧本的 4 行代码
Caddy 2 快速简单安装配置教程 – 高玩梁的博客
切换至 Caddy2 | 某不科学的博客
Caddy2 简明教程 - bleem
树莓派安装 OpenWrt 突破校园网限制 | Asttear's Blog
OpenVPN 路由设置 – 凤曦的小窝
个性化编译 LEDE 固件
盘点各种 Windows/Office 激活工具
[VirtualBox] 1、NAT 模式下端口映射
VirtualBox 虚拟机安装 openwrt 供本机使用
NUC 折腾笔记 - 安装 ESXi 7 - 苏洋博客
锐捷、赛尔认证 MentoHUST - Ubuntu 中文
How Do I Use A Client Certificate And Private Key From The IOS Keychain? | OpenVPN
比特记事簿: 笔记: 使用电信 TR069 内网架设 WireGuard 隧道异地组网
利用 GitHub API 获取最新 Releases 的版本号 | 这是只兔子
docsify - 生成文档网站简单使用教程 - SegmentFault 思否
【干货】Chrome 插件 (扩展) 开发全攻略 - 好记的博客
一看就会的 GitHub 骚操作,让你看上去像一位开源大佬
【计算机网络】了解内网、外网、宽带、带宽、流量、网速_墩墩分墩 - CSDN 博客
mac-ssh 配置 | Sail
如何科学管理你的密码
VirtualBox NAT 端口映射实现宿主机与虚拟机相互通信 | Shao Guoliang 的博客
CentOS7 配置网卡为静态 IP,如果你还学不会那真的没有办法了!
laisky-blog: 近期折腾 tailscale 的一些心得
使用 acme.sh 给 Nginx 安装 Let’ s Encrypt 提供的免费 SSL 证书 · Ruby China
acme 申请 Let’s Encrypt 泛域名 SSL 证书
从 nginx 迁移到 caddy
使用 Caddy 替代 Nginx,全站升级 https,配置更加简单 - Diamond-Blog
http.proxy - Caddy 中文文档
动手撸个 Caddy(二)| Caddy 命令行参数最全教程 | 飞雪无情的总结
Caddy | 学习笔记 - ijayer
Caddy 代理 SpringBoot Fatjar 应用上传静态资源
使用 graylog3.0 收集 open××× 日志进行审计_年轻人,少吐槽,多搬砖的技术博客_51CTO 博客
提高国内访问 github 速度的 9 种方法! - SegmentFault 思否
VM16 安装 macOS 全网最详细
2022 目前三种有效加速国内 Github
How to install MariaDB on Alpine Linux | LibreByte
局域网内电脑 - ipad 文件共享的三种方法 | 岚
多机共享键鼠软件横向测评 - 尚弟的小笔记
VLOG | ESXI 如何升级到最新版,无论是 6.5 还是 6.7 版本都可以顺滑升级。 – Vedio Talk - VLOG、科技、生活、乐分享
远程修改 ESXi 6.7 管理 IP 地址 - 腾讯云开发者社区 - 腾讯云
几乎不要钱自制远程 PLC 路由器方案
traefik 简易入门 | 个人服务器运维指南 | 山月行
更完善的 Docker + Traefik 使用方案 - 苏洋博客
MicroSD·TF 卡终极探秘 ·MLC 颗粒之谜 1 三星篇_microSD 存储卡_什么值得买
macOS 绕过公证和应用签名方法 - 走客
MiscSecNotes / 内网端口转发及穿透. md at master · JnuSimba/MiscSecNotes
我有特别的 DNS 配置和使用技巧 | Sukka's Blog
SEO:初学者完整指南
通过 OpenVPN 实现流量审计
OpenVPN-HOWTO
OpenVPN Server · Devops Roadmap
Linux 运维必备的 13 款实用工具, 拿好了~
linux 平台下 Tomcat 的安装与优化
Linux 运维跳槽必备的 40 道面试精华题
Bash 脚本进阶,经典用法及其案例 - alonghub - 博客园
推荐几个非常不错的富文本编辑器 - 走看看
在 JS 文件中加载 JS 文件的方法 - 月光博客
#JavaScript 根据需要动态加载脚本并设置自定义参数
笔记本电脑 BIOS 修改及刷写教程
跨平台加密 DNS 和广告过滤 personalDNSfilter · LinuxTOY
AdGuard Home 安装及使用指北
通过 Amazon S3 协议挂载 OSS
记一次云主机如何挂载对象存储
本文档发布于https://mrdoc.fun
-
+
首页
OpenVPN-HOWTO
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [github.com](https://github.com/izombielandgit/OpenVPN-HOWTO/blob/master/1.%20HOWTO.md) [](#1-howto)1. HOWTO ==================== [https://openvpn.net/community-resources/how-to/](https://openvpn.net/community-resources/how-to/) [OpenVPN](https://openvpn.net/)(OpenVPN 官网所有内容需科学上网才能访问)是一个功能齐全的 SSL VPN,它使用行业标准的 SSL/TLS 协议实现了 OSI 模型第 2 层(数据链路层)或第 3 层(网络层)的安全网络扩展。OpenVPN 支持基于证书、智能卡以及用户名 / 密码等多种形式的灵活的客户端认证方法,并可以通过应用于 VPN 虚拟接口的防火墙规则为指定用户或用户组设置访问控制策略。 * [1.1. 安装 OpenVPN](#11-%E5%AE%89%E8%A3%85openvpn) * [1.2. 选择使用路由还是桥接](#12-%E9%80%89%E6%8B%A9%E4%BD%BF%E7%94%A8%E8%B7%AF%E7%94%B1%E8%BF%98%E6%98%AF%E6%A1%A5%E6%8E%A5) * [1.3. 设置私有子网](#13-%E8%AE%BE%E7%BD%AE%E7%A7%81%E6%9C%89%E5%AD%90%E7%BD%91) * [1.4. 创建证书](#14-%E5%88%9B%E5%BB%BA%E8%AF%81%E4%B9%A6) * [1.5. 创建配置文件](#15-%E5%88%9B%E5%BB%BA%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6) * [1.6. 启动 VPN 并测试](#16-%E5%90%AF%E5%8A%A8vpn%E5%B9%B6%E6%B5%8B%E8%AF%95) * [1.7. 系统启动时自动运行](#17-%E7%B3%BB%E7%BB%9F%E5%90%AF%E5%8A%A8%E6%97%B6%E8%87%AA%E5%8A%A8%E8%BF%90%E8%A1%8C) * [1.8. 控制运行中的 OpenVPN 进程](#18-%E6%8E%A7%E5%88%B6%E8%BF%90%E8%A1%8C%E4%B8%AD%E7%9A%84openvpn%E8%BF%9B%E7%A8%8B) * [1.9. 服务器或客户端子网中的其他计算机互相访问](#19-%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%88%96%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%AD%90%E7%BD%91%E4%B8%AD%E7%9A%84%E5%85%B6%E4%BB%96%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BA%92%E7%9B%B8%E8%AE%BF%E9%97%AE) * [1.9.1. 防火墙规则](#191-%E9%98%B2%E7%81%AB%E5%A2%99%E8%A7%84%E5%88%99) * [1.10. 推送 DHCP 选项到客户端](#110-%E6%8E%A8%E9%80%81dhcp%E9%80%89%E9%A1%B9%E5%88%B0%E5%AE%A2%E6%88%B7%E7%AB%AF) * [1.11. 为指定客户端配置规则和访问策略](#111-%E4%B8%BA%E6%8C%87%E5%AE%9A%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE%E8%A7%84%E5%88%99%E5%92%8C%E8%AE%BF%E9%97%AE%E7%AD%96%E7%95%A5) * [1.12. 使用其他身份验证方式](#112-%E4%BD%BF%E7%94%A8%E5%85%B6%E4%BB%96%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%96%B9%E5%BC%8F) * [1.13. 使用客户端的智能卡实现双重认证](#113-%E4%BD%BF%E7%94%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E6%99%BA%E8%83%BD%E5%8D%A1%E5%AE%9E%E7%8E%B0%E5%8F%8C%E9%87%8D%E8%AE%A4%E8%AF%81) * [1.14. 路由所有客户端流量通过 VPN](#114-%E8%B7%AF%E7%94%B1%E6%89%80%E6%9C%89%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%B5%81%E9%87%8F%E9%80%9A%E8%BF%87vpn) * [1.15. 在动态 IP 地址上运行 OpenVPN 服务器](#115-%E5%9C%A8%E5%8A%A8%E6%80%81ip%E5%9C%B0%E5%9D%80%E4%B8%8A%E8%BF%90%E8%A1%8Copenvpn%E6%9C%8D%E5%8A%A1%E5%99%A8) * [1.16. 通过 HTTP 代理连接 OpenVPN 服务器](#116-%E9%80%9A%E8%BF%87http%E4%BB%A3%E7%90%86%E8%BF%9E%E6%8E%A5openvpn%E6%9C%8D%E5%8A%A1%E5%99%A8) * [1.17. 通过 OpenVPN 连接 Samba 网络共享服务器](#117-%E9%80%9A%E8%BF%87openvpn%E8%BF%9E%E6%8E%A5samba%E7%BD%91%E7%BB%9C%E5%85%B1%E4%BA%AB%E6%9C%8D%E5%8A%A1%E5%99%A8) * [1.18. 实现负载均衡 / 故障转移的配置](#118-%E5%AE%9E%E7%8E%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%95%85%E9%9A%9C%E8%BD%AC%E7%A7%BB%E7%9A%84%E9%85%8D%E7%BD%AE) * [1.19. 增强 OpenVPN 的安全性](#119-%E5%A2%9E%E5%BC%BAopenvpn%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7) * [1.20. 撤销证书](#120-%E6%92%A4%E9%94%80%E8%AF%81%E4%B9%A6) * [1.21. 关于中间人攻击的重要注意事项](#121-%E5%85%B3%E4%BA%8E%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB%E7%9A%84%E9%87%8D%E8%A6%81%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9) [](#11-安装openvpn)1.1. 安装 OpenVPN -------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#install) 可以[在这里](https://openvpn.net/index.php/open-source/downloads.html)下载 OpenVPN 源代码和 Windows 安装程序。最近的版本 (2.2 及以后版本) 也发布了 Debian 和 RPM 包(.deb 和. rpm)。详情查看 [OpenVPN wiki](https://community.openvpn.net/openvpn)。出于安全考虑,建议下载完毕后检查一下文件的[签名信息](https://openvpn.net/index.php/open-source/documentation/sig.html)。OpenVPN 可执行文件提供了服务器和客户端的所有功能,因此服务器和客户端都需要安装 OpenVPN 的可执行文件。 **Linux 安装事项(使用 RPM 包管理工具)** 如果你使用的 Linux 发行版支持 RPM 包管理工具,例如:RedHat、CentOS、Fedora、SUSE 等。最好使用这种方法来安装。最简单的方法就是找到一个可以在当前 Linux 发行版上使用的二进制 RPM 文件。你也可以使用如下命令创建 (build) 你自己的二进制 RPM 文件: ``` rpmbuild -tb openvpn-[version].tar.gz ``` 有了`.rpm`格式的文件,就可以使用如下常规命令来安装它。 ``` rpm -ivh openvpn-[details].rpm ``` 或者升级现有的 OpenVPN 版本: ``` rpm -Uvh openvpn-[details].rpm ``` 安装 OpenVPN 的 RPM 包,需要如下这些依赖软件包: * openssl (SSL 协议及相关内容的开源实现) * lzo (无损压缩算法) * pam (身份验证模块) 此外,如果自己创建 (build) 二进制 RPM 包,需要如下几个依赖: * openssl-devel * lzo-devel * pam-devel 可以查看 [openvpn.spec](https://openvpn.net/index.php/open-source/documentation/install.html#rpm) 文件,该文件包含了在 RedHat Linux 9 上创建 RPM 包,或者在减少依赖的情况下创建 RPM 包的更多信息。 **Linux 安装事项(非 RPM)** 如果你使用的系统是 Debian、Gentoo 或其他不基于 RPM 的 Linux 发行版,你可以使用当前发行版指定的软件包管理机制,例如 Debian 的`apt-get`或者 Gentoo 的`emerge`。 ``` apt-get install openvpn # 使用apt-get安装OpenVPN emerge openvpn # 使用emerge安装OpenVPN ``` 也可以使用常规的`./configure`方法在安装 Linux 上安装 OpenVPN。首先,解压`.tar.gz`文件: ``` tar xfz openvpn-[version].tar.gz ``` 然后跳转到 OpenVPN 的顶级目录(`top-level directory`实际上就是 OpenVPN 解压后的目录),输入: ``` ./configure make make install ``` 通过`./configure`方式进行 OpenVPN 的编译安装之前,仍然需要先安装 OpenVPN 的依赖软件包`openssl`、`lzo`、`pam`。 **Windows 安装事项** 对 Windows 系统而言,可以直接在下载 exe 格式的可执行文件来安装 OpenVPN。OpenVPN 只能够在 Windows XP 及以上版本的系统中运行。还要注意,必须具备管理员权限才能够安装运行 OpenVPN(该限制是 Windows 自身造成的,而不是 OpenVPN)。安装 OpenVPN 之后,你可以用 Windows 后台服务的方式启动 OpenVPN 来绕过该限制;在这种情况下,非管理员用户也能够正常访问 VPN。你可以点击查看[关于 OpenVPN + Windows 权限问题的更多讨论](http://openvpn.se/files/howto/openvpn-howto_run_openvpn_as_nonadmin.html)。 官方版的 OpenVPN Windows 安装程序自带 [OpenVPN GUI](https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI),OpenVPN GUI 允许用户通过一个托盘程序来管理 OpenVPN 连接。也可以使用其他的 [GUI 程序](https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI)。 安装 OpenVPN 之后,OpenVPN 将会与扩展名为`.ovpn`的文件进行关联。想要运行 OpenVPN,可以: * 右键点击 OpenVPN 配置文件`.ovpn`,在弹出的关联菜单中选择【Start OpenVPN on this configuration file】即可使用该配置文件启动 OpenVPN。运行 OpenVPN 后,可以使用快捷键`F4`来退出程序。 * 以命令提示符的方式运行 OpenVPN,例如:`openvpn myconfig.ovpn`。运行之后,同样可以使用快捷键`F4`来退出 VPN。 * 在 OpenVPN 安装路径`/config`目录(一般默认为`C:\Program Files\OpenVPN\config`)中放置一个或多个`.ovpn`格式的配置文件,然后启动名为 OpenVPN Service 的 Windows 服务。你可以点击【开始】->【控制面板】->【管理工具】->【服务】,从而进入 Windows 服务管理界面。 **Mac OS X 安装事项** Angelo Laub 和 Dirk Theisen 已经开发出了 [OpenVPN GUI for OS X](https://tunnelblick.net/)。 **其他操作系统** 通常情况下,其他操作系统也可以使用`./configure`方法来安装 OpenVPN,或者也可以自行查找一个适用于你的操作系统 / 发行版的 OpenVPN 接口或安装包。 ``` ./configure make make install ``` 更多安装说明参阅[这里](https://openvpn.net/index.php/open-source/documentation/install.html?start=1)。 [](#12-选择使用路由还是桥接)1.2. 选择使用路由还是桥接 --------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#vpntype) 查看 “路由 VS. 以太网桥接” 的 [FAQ](https://community.openvpn.net/openvpn/wiki/FAQ#bridge1)。也可以查看 OpenVPN [以太网桥接](https://openvpn.net/index.php/open-source/documentation/miscellaneous/76-ethernet-bridging.html)页面以了解关于桥接的更多事项和细节。 总的来说,对于大多数人而言,“路由模式”可能是更好的选择,因为它可以比 “桥接模式” 更高效更简单地搭建一个 VPN(基于 OpenVPN 自带的配置)。路由模式还提供了更强大的对指定客户端的访问权限进行控制的能力。 推荐使用 “路由模式”,除非你需要用到只有“桥接模式” 才具备的某些功能特性,例如: * VPN 需要处理非 IP 协议,例如 IPX。 * 在 VPN 网络中运行的应用程序需要用到网络广播 (network broadcasts),例如:局域网游戏。 * 你想要在没有 Samba 或 WINS 服务器的情况下,能够通过 VPN 浏览 Windows 文件共享。 [](#13-设置私有子网)1.3. 设置私有子网 ------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#numbering) 创建一个 VPN 需要借助私有子网将不同地方的成员连接在一起。 互联网号码分配机构 (IANA) 专为私有网络保留了以下三块 IP 地址空间(制定于 RFC 1918 规范中): * 10.0.0.0-10.255.255.255(10/8 prefix (前缀) ) * 172.16.0.0-172.31.255.255(172.16/12 prefix (前缀) ) * 192.168.0.0-192.168.255.255(192.168/16 prefix (前缀) ) 在 VPN 配置中使用这些地址。对选择 IP 地址并将 IP 地址冲突或子网冲突的发生概率降到最低而言,这一点非常重要。以下是需要避免的冲突类型: * VPN 中不同的网络场所使用相同的局域网子网编号所产生的冲突。 * 远程访问连接自身使用的私有子网与 VPN 的私有子网发生冲突。 简而言之,处于不同局域网的客户端和客户端之间,它们自身所在的局域网 IP 段不要发生冲突;客户端自身所在的局域网 IP 段也不要和 VPN 使用的局域网 IP 段发生冲突。 举个例子,假设你使用了流行的`192.168.0.0/24`作为 VPN 子网。现在,你尝试在一个网吧内连接 VPN,该网吧的 WIFI 局域网使用了相同的子网。这将产生一个路由冲突,因为计算机不知道`192.168.0.1`是指本地 WIFI 的网关,还是指 VPN 上的相同地址。 再举个例子,假设你想通过 VPN 将多个网络场所连接在一起,但是每个网络场所都使用了`192.168.0.0/24`作为自己的局域网子网。如果不添加一个复杂的 NAT 翻译层,它们将无法工作。因为这些网络场所没有唯一的子网来标识它们自己,VPN 不知道如何在多个网络场所之间路由数据包。 最佳的解决方案是避免使用`10.0.0.0/24`或者`192.168.0.0/24`作为 VPN 的私有子网。相反,你应该使用一些在你可能连接 VPN 的场所(例如咖啡厅、酒店、机场)不太可能使用的私有子网。最佳的候选者应该是在浩瀚的`10.0.0.0/8`网络块中间选择一个子网(例如:`10.66.77.0/24`)。 总的来说,为了避免跨多个网络场所的 IP 编号冲突,请始终使用唯一的局域网子网编号。 [](#14-创建证书)1.4. 创建证书 --------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#pki) 以下并非按照原文来的。 可以从发行版软件仓库直接安装,安装后操作如下: `cd /usr/share/easy-rsa/2.0` 编辑`vars`文件: ``` # 密钥长度为2048,如果是1024可改为2048 export KEY_SIZE=2048 # CA证书有效时间3650天,根据需要修改 export CA_EXPIRE=3650 # 密钥有效时间3650天,根据需要修改 export KEY_EXPIRE=3650 export KEY_COUNTRY="CN" # 国家 export KEY_PROVINCE="SC" # 省份 export KEY_CITY="CD" # 城市 export KEY_ORG="x" # 组织机构 export KEY_EMAIL="x@x.com" # 邮箱 export KEY_OU="x" # 单位或部门 export KEY_NAME="OpenVPNServer" # openvpn服务器的名称 ``` `source ./vars` # 初始化 `./clean-all` # 清理 keys `./build-ca` # 生成`ca.crt`和`ca.key` `./build-key-server server` # 生成`server.crt`,`server.csr`和`server.key` `./build-dh` # 生成`dh2048.pem` `openvpn --genkey --secret ta.key` # 生成`ta.key` keys 文件详解可[参考这里](http://www.williamlong.info/archives/3814.html)。 GitHub 上的 easy-rsa 最新版本为 easy-rsa3,生成证书命令有一些变化,如下操(有问题可官网查看或运行`./easyrsa help`): ``` wget https://github.com/OpenVPN/easy-rsa/archive/master.zip unzip master.zip cd easy-rsa-master/easyrsa3 cp vars.example vars ``` 编辑`vars`文件: ``` # 取消注释并修改对应内容 set_var EASYRSA_REQ_COUNTRY "US" # 国家 set_var EASYRSA_REQ_PROVINCE "California" # 省份 set_var EASYRSA_REQ_CITY "San Francisco" # 城市 set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" # 组织机构 set_var EASYRSA_REQ_EMAIL "me@example.net" # 邮箱 set_var EASYRSA_REQ_OU "My Organizational Unit" # 单位或部门 set_var EASYRSA_KEY_SIZE 2048 # 密钥长度2048 set_var EASYRSA_CA_EXPIRE 3650 # CA有效期3650天 set_var EASYRSA_CERT_EXPIRE 3650 # CERT有效期3650天 # 客户端使用--ns-cert-type,取消下行注释并改值改为yes,(一般不推荐使用,而推荐使用--remote-cert-tls功能) #set_var EASYRSA_NS_SUPPORT "no" # 其他内容可以根据自己需要修改 ``` 保存后继续运行,生成服务器端证书: ``` ./easyrsa init-pki # 初始化,会清空已有信息,并在当前目录创建PKI目录,用于存储一些中间变量及最终生成的证书 ./easyrsa build-ca # 创建根证书,会提示设置密码,用于ca对之后生成的server和client证书签名时使用,然后提示设置Common Name ./easyrsa gen-req server nopass # 创建server证书和private key,nopass表示不加密private key,然后提示设置Common Name(使用与上一步不同的) ./easyrsa sign-req server server # 给server证书签名,确认信息后输入yes,然后输入build-ca时设置的密码 ./easyrsa gen-dh # 创建Diffie-Hellman ``` OpenVPN 服务端需要的文件如下: `easyrsa3/pki/ca.crt` `easyrsa3/pki/private/server.key` `easyrsa3/pki/issued/server.crt` `easyrsa3/pki/dh.pem` `openvpn --genkey --secret ta.key` # 生成`ta.key`的命令相同 生成客户端证书(如果客户端不使用证书认证,这一步就不需要了),在与上面生成服务端证书的 easy-rsa 不同的文件夹重新解压一次(网上查的资料说是在新目录重新生成,不知道可否直接在刚才的目录使用,未测试,如果要测试注意不要再次运行`./easyrsa init-pki`),进入新的`easy-rsa-master/easyrsa3`目录后同样设置一下`vars`文件,然后开始生成证书: ``` ./easyrsa init-pki ./easyrsa gen-req client1 nopass # 创建client1证书和private key,nopass表示不加密private key,然后提示设置Country Name(设置与上面不同的) ``` 切换到前面生成 CA 的目录,运行: ``` ./easyrsa import-req [上一步生成客户端证书的路径]/easyrsa3/pki/reqs/client1.req client1 # 导入req ./easyrsa sign-req client client1 # # 给client1证书签名,确认信息后输入yes,然后输入build-ca时设置的密码 ``` 文件位置如下: `easyrsa3/pki/issued/client.crt` `easyrsa3/pki/private/client.key` **证书相关文件** <table><thead><tr><th>文件名</th><th>谁需要</th><th>作用</th><th>是否需保密</th></tr></thead><tbody><tr><td>ca.crt</td><td>服务器 + 所有客户端</td><td>根 CA 证书</td><td>NO</td></tr><tr><td>ca.key</td><td>密钥签名机</td><td>根 CA 密钥</td><td>YES</td></tr><tr><td>dh{n}.pem</td><td>服务器</td><td>迪菲 · 赫尔曼参数</td><td>NO</td></tr><tr><td>server.crt</td><td>服务器</td><td>服务器证书</td><td>NO</td></tr><tr><td>server.key</td><td>服务器</td><td>服务器密钥</td><td>YES</td></tr><tr><td>client1.crt</td><td><relin-hc>client1</relin-hc></td><td><relin-hc>Client1 证书</relin-hc></td><td>NO</td></tr><tr><td>client1.key</td><td><relin-hc>client1</relin-hc></td><td><relin-hc>Client1 密钥</relin-hc></td><td>YES</td></tr><tr><td>client2.crt</td><td><relin-hc>client2</relin-hc></td><td><relin-hc>Client2 证书</relin-hc></td><td>NO</td></tr><tr><td>client2.key</td><td><relin-hc>client2</relin-hc></td><td><relin-hc>Client2 密钥</relin-hc></td><td>YES</td></tr></tbody></table> 关于证书、密钥安全性的问题可查看原文。 [](#15-创建配置文件)1.5. 创建配置文件 ------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#config) **取得示例配置文件** 最好使用 [OpenVPN 示例配置文件](../2. 配置文件说明. html) 作为配置起点。这些文件可以在下列地方找到: * OpenVPN 源代码版的`sample-config-files`目录。 * 如果通过 RPM 或 DEB 来安装 OpenVPN,则为`/usr/share/doc/packages/openvpn`或`/usr/share/doc/openvpn`中的`sample-config-files`目录。 * Windows 系统中的【开始】->【所有程序】->【OpenVPN】->【Shortcuts】->【OpenVPN Sample (样本) Configuration Files】,也就是 OpenVPN 安装路径`/sample-config`目录。 注意:在 Linux、BSD 或类 Unix 系统中,示例配置文件叫做`server.conf`和`client.conf`。在 Windows 中叫做`server.ovpn`和`client.ovpn`。 **编辑服务器端配置文件** 服务器端配置文件示例是 OpenVPN 服务器端配置的最佳起始点。 该示例配置将使用一个虚拟的 TUN 网络接口(路由模式),在 UDP 端口 1194(OpenVPN 的官方端口号)监听远程连接,并从子网`10.8.0.0/24`中为连接的客户端分配虚拟地址。 在使用示例配置文件之前,先编辑`ca`、`cert`、`key`、`dh`参数,将它们分别指向对应文件。 此时,服务器端配置文件是可用的,但可以进一步自定义该文件: * 如果你使用的是[以太网桥接](https://openvpn.net/index.php/open-source/documentation/miscellaneous/76-ethernet-bridging.html)模式,必须使用`server-bridge`和`dev tap`指令来替代`server`和`dev tun`指令。 * 如果想让你的 OpenVPN 服务器监听一个 TCP 端口,而不是 UDP 端口,使用`proto tcp`替代`proto udp`(如果想同时监听 UDP 和 TCP 端口,必须启动两个单独的 OpenVPN 实例)。 * 如果你想使用`10.8.0.0/24`范围之外的虚拟 IP 地址,修改`server`指令。记住,虚拟 IP 地址范围必须是一个你当前网络未使用的私有范围。 * 如果你想让通过 VPN 连接的客户端和客户端之间能够互访,启用`client-to-client`指令(去掉注释)。默认情况下,客户端只能够访问服务器。 * 如果你正在使用 Linux、BSD 或类 Unix 操作系统,你可以使启用`user nobody`和`group nobody`指令来提高安全性。 如果想要在同一计算机上运行多个 OpenVPN 实例,每一个示例都应该使用不同的配置文件。可能存在下列情形: * 每个示例使用不同的端口号(UDP 和 TCP 协议使用不同的端口空间,因此你可以运行一个后台进程并同时监听 UDP-1194 和 TCP-1194)。 * 如果你使用的是 Windows 系统,每个 OpenVPN 配置都需要有自己的 TAP-Windows 适配器。你可以通过【开始】->【所有程序】->【TAP-Windows】->【Add a new TAP-Windows virtual (虚拟) ethernet adapter】来添加一个额外的适配器。 * 如果你运行多个相同目录的 OpenVPN 实例,请确保编辑那些会创建输出文件的指令,以便于多个实例不会覆盖掉对方的输出文件。这些指令包括`log`、`log-append`、`status`和`ifconfig-pool-persist`。 **编辑客户端配置文件** 客户端配置示例文件(在 Linux/BSD/Unix 中为`client.conf`,在 Windows 中为`client.ovpn`)参照了服务器配置示例文件的默认指令设置。 * 与服务器配置文件类似,首先编辑`ca`、`cert`和`key`参数,使它们指向对应文件。注意,每个客户端都应该有自己的证书 / 密钥对。只有`ca`文件是 OpenVPN 和所有客户端通用的。 * 下一步,编辑`remote`指令,将其指向 OpenVPN 服务器的主机名 / IP 地址和端口号(如果 OpenVPN 服务器在防火墙或 NAT 网关之后的单网卡机器上运行,请使用网关的公网 IP 地址,和你在网关中配置的转发到 OpenVPN 服务器的端口号)。 * 最后,确保客户端配置文件和用于服务器配置的指令保持一致。主要检查 dev(dev 或 tap)和 proto(udp 或 tcp)指令是否一致。此外,如果服务器和客户端配置文件都使用了`comp-lzo`和`fragment`指令,也需要保持一致。 [](#16-启动vpn并测试)1.6. 启动 VPN 并测试 ------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#start) **启动服务器** 首先,确保 OpenVPN 服务器能够正常连接网络。这意味着: * 开启防火墙上的 UDP-1194 端口(或者你配置的其他端口)。 * 或者,创建一个端口转发规则,将防火墙 / 网关的 UDP-1194 端口转发到运行 OpenVPN 服务器的计算机上。 下一步,[确保 TUN/TAP 接口没有被防火墙屏蔽](https://community.openvpn.net/openvpn/wiki/FAQ#firewall)。 为了简化故障排除,最好使用命令行来初始化启动 OpenVPN 服务器(或者在 Windows 上右击. ovpn 文件),而不是以后台进程或服务的方式启动: ``` openvpn [服务器配置文件] ``` 正常的服务器启动应该像这样: ``` Sun Feb 6 20:46:38 2005 OpenVPN 2.0_rc12 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb 5 2005 Sun Feb 6 20:46:38 2005 Diffie-Hellman initialized with 1024 bit key Sun Feb 6 20:46:38 2005 TLS-Auth MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ] Sun Feb 6 20:46:38 2005 TUN/TAP device tun1 opened Sun Feb 6 20:46:38 2005 /sbin/ifconfig tun1 10.8.0.1 pointopoint 10.8.0.2 mtu 1500 Sun Feb 6 20:46:38 2005 /sbin/route add -net 10.8.0.0 netmask 255.255.255.0 gw 10.8.0.2 Sun Feb 6 20:46:38 2005 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:23 ET:0 EL:0 AF:3/1 ] Sun Feb 6 20:46:38 2005 UDPv4 link local (bound): [undef]:1194 Sun Feb 6 20:46:38 2005 UDPv4 link remote: [undef] Sun Feb 6 20:46:38 2005 MULTI: multi_init called, r=256 v=256 Sun Feb 6 20:46:38 2005 IFCONFIG POOL: base=10.8.0.4 size=62 Sun Feb 6 20:46:38 2005 IFCONFIG POOL LIST Sun Feb 6 20:46:38 2005 Initialization Sequence Completed ``` **启动客户端** 和服务器端配置一样,最好使用命令行来初始化启动 OpenVPN 客户端(在 Windows 上,也可以直接右击 client.ovpn 文件),而不是以后台进程或服务的方式来启动。 ``` openvpn [客户端配置文件] ``` Windows 上正常的客户端启动看起来与前面服务器端的输出非常相似,并且应该以`Initialization Sequence Completed`信息作为结尾。 尝试从客户端通过 VPN 发送`ping`命令。 如果你使用的是路由模式(例如:在服务器配置文件中设置`dev tun`),运行: ``` ping 10.8.0.1 ``` 如果使用桥接模式(例如:在服务器配置文件中设置`dev tap`),尝试 ping 一个服务器端的以太网子网中的 IP 地址。 如果能够`ping`成功,那么就连接成功了。 **故障排除** 如果`ping`失败或者无法完成 OpenVPN 客户端的初始化,这里列出了一个常见问题以及对应解决方案的清单: 1、得到错误信息:`TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)`。该错误表明客户端无法与服务器建立一个网络连接。 解决方案: * 确保客户端配置中使用的服务器主机名 / IP 地址和端口号是正确的。 * 如果 OpenVPN 服务器所在计算机只有单个网卡,并处于受保护的局域网内,请确保服务器端的网关防火墙使用了正确的端口转发规则。举个例子,假设你的 OpenVPN 服务器在某个局域网内,IP 为`192.168.4.4`,并在 UDP 端口 1194 上监听客户端连接。服务于子网`192.168.4.x`的 NAT 网关应该有一个端口转发规则,该规则将公网 IP 地址的 UDP 端口 1194 转发到`192.168.4.4`。 * 打开服务器防火墙,允许外部连接通过 UDP-1194 端口(或者在服务器配置文件中设置的其他端口)。 2、得到错误信息:`Initialization Sequence Completed with errors`。该错误发生在:(a) 你的 Windows 系统没有一个正在运行的 DHCP 客户端服务,(b) 或者你在 XP SP2 上使用了某些第三方的个人防火墙。 解决方案: * 启动 DHCP 客户端服务器,并确保在 XP SP2 系统中使用的是一个工作正常的个人防火墙。 3、得到信息`Initialization Sequence Completed`但是`ping`测试失败。这通常意味着服务器或客户端的防火墙屏蔽了 TUN/TAP 接口,从而阻塞了 VPN 网络。 解决方案: * 禁用客户端 TUN/TAP 接口上的防火墙(如果存在的话)。以 Windows XP SP2 为例,你可以进入【Windows 安全中心】->【Windows 防火墙】->【高级】,并取消选中 TAP-Windows 适配器前面的复选框(从安全角度来说,禁止客户端防火墙屏蔽 TUN/TAP 接口通常是合理的,这是在告诉防火墙不要阻止可信的 VPN 流量)。此外,也需要确保服务器的 TUN/TAP 接口没有被防火墙屏蔽(不得不说的是,选择性地设置服务器端 TUN/TAP 接口的防火墙有助于提高一定的安全性,请参考访问策略部分)。 * 笔者注:也有可能本身已连通但是`ping`的主机防火墙阻止了 ICMP,可以进行相关设置后再尝试 4、当采用 UDP 协议的配置启动时,出现连接中断,并且服务器日志文件显示下行: ``` TLS: Initial packet from x.x.x.x:x, sid=xxxxxxxx xxxxxxxx ``` 但客户端的日志文件不会显示相同的信息。 解决方案: * 你只有一个从客户端到服务器的单向连接。而从服务器到客户端的方向则被(通常是客户端这边的)防火墙阻挡了。该防火墙可能是运行于客户端的个人软件防火墙,或是客户端的 NAT 路由网关。请修改防火墙以允许从服务器到客户端的 UDP 数据包返回。 想了解更多额外的故障排除信息,请查看 [FAQ](https://community.openvpn.net/openvpn/wiki/FAQ)。 [](#17-系统启动时自动运行)1.7. 系统启动时自动运行 ------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#startup) 关于这个问题并没有所谓的标准答案,也就是说大多数系统都有不同的方式来配置在系统启动时自动运行后台进程 / 服务。想要默认就具备该功能设置的最佳方式就是以软件包的形式安装 OpenVPN,例如通过 Linux 系统的 RPM、DEB 或者使用 Windows 安装程序。 **Linux 系统** 如果在 Linux 上通过 RPM 或 DEB 软件包来安装 OpenVPN,安装程序将创建一个`initscript`。执行该脚本,`initscript`将会扫描`/etc/openvpn`目录下`.conf`格式的配置文件,如果能够找到,将会为每个文件分别启动一个独立的 OpenVPN 后台进程。 **Windows 系统** Windows 安装程序将会建立一个服务器包装器 (Service Wrapper),不过默认情况下其处于关闭状态。如果想激活它,请进入【控制面板】->【管理工具】->【服务】,然后右键点击 "OpenVPN Service",在弹出的关联菜单中单击【属性】,并将属性面板中的 "启动类型" 设为 "自动"。OpenVPN 服务将会在下次重启系统时自动运行。 启动后,OpenVPN 服务包装器将会扫描 OpenVPN 安装路径`/config`文件夹下`.ovpn`格式的配置文件,然后为每个文件启动一个单独的 OpenVPN 进程。 [](#18-控制运行中的openvpn进程)1.8. 控制运行中的 OpenVPN 进程 --------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#control) **运行于 Linux/BSD/Unix** * SIGUSR1 # 有条件的重新启动,设计用于没有 root (根) 权限的重启 * SIGHUP # 硬重启 * SIGUSR2 # 输出连接统计信息到日志文件或 syslog 中 * SIGTERM, SIGINT # 退出 使用`writepid`指令将 OpenVPN 的后台进程 PID 写入到一个文件中,这样你就知道该向哪里发送信号(如果以`initscript`方式启动 OpenVPN,该脚本可能已经通过 openvpn 命令行中的指令 --writepid 达到了该目的)。 **以 GUI 形式在 Windows 上运行** 请查看 [OpenVPN GUI 页面](https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI)。 **运行于 Windows 命令提示符窗口** 在 Windows 中,可以通过右击一个 OpenVPN 配置文件(.ovpn 文件),然后选择 “Start OpenVPN on this config file” 来启动 OpenVPN。 一旦以这种方式运行,你可以使用如下几种按键命令: * `F1` # 有条件的重启 (无需关闭 / 重新打开 TAP (水龙头) 适配器) * `F2` # 显示连接统计信息 * `F3` # 硬重启 * `F4` # 退出 **以 Windows 服务方式运行** 在 Windows 中,当 OpenVPN 以服务方式启动时,控制方式是: * 通过服务控制管理器(控制面板 -> 管理工具 -> 服务),其中提供了启动 / 终止操作。 * 通过管理接口(详情参考下面)。 **修改使用中的 OpenVPN 配置** 虽然大多数配置更改必须重启服务器才能生效,但仍然有两个指令可以用于文件动态更新,并且能够直接生效而无需重启服务器进程。 * `client-config-dir` # 该指令设置一个客户端配置文件夹,OpenVPN 服务器将会在每个外部连接到来时扫描该目录中的文件,用以查找为当前连接指定的客户端配置文件(详情查看[手册页面](https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html))。该目录中的文件可以随时更新,而无需重启服务器。请注意,该目录中发生的更改只对新的连接起作用,不包括之前已经存在的连接。如果你想通过指定客户端的配置文件更改来直接影响当前正在连接的客户端(或者该连接已经断开,但它在服务器中的实例对象并没有超时),你可以通过管理接口来杀掉该客户端的实例对象(详见下方描述)。这将导致客户端重新连接并使用新的`client-config-dir`文件。 * `crl-verify` # 该指令指定一个证书撤销列表 (CRL) 文件,相关描述请参考后面的撤销证书部分。该 CRL 文件能够在运行中被修改,并且修改可以直接对新的连接或那些正在重新建立 SSL/TLS 通道的现有连接(默认每小时重新建立一次通道)生效。如果你想杀掉一个证书已经添加到 CRL 中,但目前已连接的客户端,请使用管理接口(详见下方描述)。 **状态信息文件** 默认的 server.conf 文件有这样一行: ``` status openvpn-status.log ``` OpenVPN 将每分钟输出一次当前客户端连接列表到文件 openvpn-status.log 中。 **使用管理接口** [OpenVPN 管理接口](https://openvpn.net/index.php/open-source/documentation/miscellaneous/79-management-interface.html)可以对正在运行的 OpenVPN 进程进行大量的控制操作。 你可以通过远程登录管理接口的端口来直接使用管理接口,或者使用连接到管理接口的 [OpenVPN GUI](https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI) 来间接使用管理接口。 要启用一个服务器或客户端的管理接口,在配置文件中添加如下指令: ``` management localhost 7505 ``` 这将告诉 OpenVPN 专为管理接口客户端监听 TCP 端口 7505(端口 7505 是随意的选择,也可以使用其他任何闲置的端口)。 OpenVPN 运行后,可以使用`telnet`客户端连接管理接口。例如: ``` ai:~ # telnet localhost 7505 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. >INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info help Management Interface for OpenVPN 2.4.4 x86_64-redhat-linux-gnu [Fedora EPEL patched] [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 26 2017 Commands: auth-retry t : Auth failure retry mode (none,interact,nointeract). bytecount n : Show bytes in/out, update every n secs (0=off). echo [on|off] [N|all] : Like log, but only show messages in echo buffer. exit|quit : Close management session. forget-passwords : Forget passwords entered so far. help : Print this message. hold [on|off|release] : Set/show hold flag to on/off state, or release current hold and start tunnel. kill cn : Kill the client instance(s) having common name cn. kill IP:port : Kill the client instance connecting from IP:port. load-stats : Show global server load stats. log [on|off] [N|all] : Turn on/off realtime log display + show last N lines or 'all' for entire history. mute [n] : Set log mute level to n, or show level if n is absent. needok type action : Enter confirmation for NEED-OK request of 'type', where action = 'ok' or 'cancel'. needstr type action : Enter confirmation for NEED-STR request of 'type', where action is reply string. net : (Windows only) Show network info and routing table. password type p : Enter password p for a queried OpenVPN password. remote type [host port] : Override remote directive, type=ACCEPT|MOD|SKIP. proxy type [host port flags] : Enter dynamic proxy server info. pid : Show process ID of the current OpenVPN process. pkcs11-id-count : Get number of available PKCS#11 identities. pkcs11-id-get index : Get PKCS#11 identity at index. client-auth CID KID : Authenticate client-id/key-id CID/KID (MULTILINE) client-auth-nt CID KID : Authenticate client-id/key-id CID/KID client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason text R and optional client reason text CR client-kill CID [M] : Kill client instance CID with message M (def=RESTART) env-filter [level] : Set env-var filter level client-pf CID : Define packet filter for client CID (MULTILINE) rsa-sig : Enter an RSA signature in response to >RSA_SIGN challenge Enter signature base64 on subsequent lines followed by END certificate : Enter a client certificate in response to >NEED-CERT challenge Enter certificate base64 on subsequent lines followed by END signal s : Send signal s to daemon, s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2. state [on|off] [N|all] : Like log, but show state history. status [n] : Show current daemon status info using format #n. test n : Produce n lines of output for testing/debugging. username type u : Enter username u for a queried OpenVPN username. verb [n] : Set log verbosity level to n, or show if n is absent. version : Show current version number. END exit Connection closed by foreign host. ai:~ # ``` [](#19-服务器或客户端子网中的其他计算机互相访问)1.9. 服务器或客户端子网中的其他计算机互相访问 ----------------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#scope) VPN 既然能够让服务器和客户端之间具备点对点的通信能力,那么扩展 VPN 的作用范围,从而使客户端能够访问服务器所在网络的其他计算机,而不仅仅是服务器自己,也是可能办得到的。 **包含基于桥接模式的 VPN 服务器端的多台计算机 (dev tap (水龙头) )** 使用[以太网桥接](https://openvpn.net/index.php/open-source/documentation/miscellaneous/76-ethernet-bridging.html)的好处之一就是无需进行任何额外的配置就可以实现该目的。 **包含基于桥接模式的 VPN 客户端的多台计算机 (dev tap (水龙头) )** 这需要更加复杂的设置(实际操作可能并不复杂,但详细解释就比较麻烦): * 必须将客户端的 TAP (水龙头) 接口与连接局域网的网卡进行桥接。 * 必须手动设置客户端 TAP 接口的 IP / 子网掩码。 * 必须配置客户端计算机使用桥接子网中的 IP / 子网掩码,这可能要通过[查询 OpenVPN 服务器的 DHCP 服务器](https://openvpn.net/index.php/open-source/documentation/install.html?start=1)来完成。 **包含基于路由模式的 VPN 服务器端的多台计算机 (dev tun)** 假设服务器端所在局域网的网段为`10.66.0.0/24`,服务器 IP 地址为`10.66.0.5`,VPN IP 地址池使用`10.8.0.0/24`作为 OpenVPN 服务器配置文件中`server`指令的传递参数。 首先,你必须声明,对于 VPN 客户端而言,`10.66.0.0/24`网段是可以通过 VPN 进行访问的。你可以通过在服务器端配置文件中简单地配置如下指令来实现该目的: ``` push "route 10.66.0.0 255.255.255.0" ``` 下一步,必须在服务器端的局域网网关创建一个路由,从而将 VPN 的客户端网段`10.8.0.0/24`路由到 OpenVPN 服务器(只有 OpenVPN 服务器和局域网网关不在同一计算机才需要这样做)。 另外,确保已经在 OpenVPN 服务器所在计算机上启用了 [IP](https://community.openvpn.net/openvpn/wiki/FAQ#ip-forward) 和 [TUN/TAP](https://community.openvpn.net/openvpn/wiki/FAQ#firewall) 转发(参考下面内容)。 **包含基于路由模式的 VPN 客户端的多台计算机 (dev tun)** 在典型的远程访问方案中,客户端都是作为单一的计算机连接到 VPN。但是,假设客户端计算机是本地局域网的网关(例如一个家庭办公室),并且你想要让客户端局域网中的每台计算机都能够通过 VPN。 假设你的客户端局域网网段为`192.168.4.0/24`,客户端 IP 地址为`192.168.4.10`,VPN 客户端使用的证书的 Common Name 为`client2`。目标是建立一个客户端局域网的计算机和服务器局域网的计算机都能够通过 VPN 进行相互通讯。 在创建之前,下面是一些基本的前提条件: * 客户端局域网网段(本例中是`192.168.4.0/24`)不能和 VPN 的服务器或任意客户端使用相同的网段。每一个以路由方式加入到 VPN 的子网网段都必须是唯一的。 * 该客户端的证书的 Common (常见) Name 必须是唯一的(本例中是`client2`),并且 OpenVPN 服务器配置文件不能使用`duplicate-cn`标记。 首先,确保该客户端所在计算机已经启用了 IP 和 TUN/TAP 转发。 各操作系统[开启 IP 和 TUN/TAP 转发的设置](https://community.openvpn.net/openvpn/wiki/265-how-do-i-enable-ip-forwarding): **Windows**([官网 IPEnableRouter 相关文章`https://technet.microsoft.com/en-us/library/cc962461.aspx`](https://technet.microsoft.com/en-us/library/cc962461.aspx)): 注册表编辑器`HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters`将`IPEnableRouter`的值改为`1`;运行`services.msc`将 “ Routing (路线) and Remote (远程) Access (访问) ” 设置为自动并启动; 检查:运行`ipconfig -all`,查看 “Windows IP 配置” 中显示`IP 路由已启用: 是` **Linux**: `echo 1 > /proc/sys/net/ipv4/ip_forward` 如果不想重启后失效,运行: ``` echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p ``` 运行`cat /proc/sys/net/ipv4/ip_forward`检查状态。 **OS X**: `sudo sysctl -w net.inet.ip.forwarding=1` 下一步,需要在服务器端做一些必要的配置更改。如果当前的服务器配置文件没有引用一个客户端配置目录,添加一个: ``` client-config-dir ccd ``` 在上面的指令中,`ccd`是一个已经在 OpenVPN 服务器运行的默认目录中预先创建好的文件夹的名称。在 Linux 中,运行的默认目录往往是`/etc/openvpn`;在 Windows 中,其通常是 OpenVPN 安装路径`/config`。当一个新的客户端连接到 OpenVPN 服务器,后台进程将会检查配置目录(这里是`ccd`)中是否存在一个与连接的客户端的 Common (常见) Name 匹配的文件(这里是`client2`)。如果找到了匹配的文件,OpenVPN 将会读取该文件,作为附加的配置文件指令来处理,并应用于该名称的客户端。 下一步就是在`ccd`目录中创建一个名为`client2`的文件。该文件应该包含如下内容: ``` iroute 192.168.4.0 255.255.255.0 ``` 这将告诉 OpenVPN 服务器:子网网段`192.168.4.0/24`应该被路由到`client2`。 接着,在 OpenVPN 服务器配置文件(**不是**`ccd/client2`文件)中添加如下指令: ``` route 192.168.4.0 255.255.255.0 #如果服务端使用`topology subnet`,添加路由使用下面的方式(需要指定网关) #route 192.168.4.0 255.255.255.0 10.8.0.1 ``` `route`语句控制从系统内核到 OpenVPN 服务器的路由,`iroute`控制从 OpenVPN 服务器到远程客户端的路由(不是太懂,照做就可以了)。 下一步,请考虑是否允许`client2`所在的子网(192.168.4.0/24)与 OpenVPN 服务器的其他客户端进行相互通讯。如果允许,在服务器配置文件中添加如下语句(笔者注:可以在`ccd`对应用户名加入,可以更精确控制使用范围,client-to-client 只能在服务器配置文件中设置): ``` client-to-client push "route 192.168.4.0 255.255.255.0" ``` OpenVPN 服务器将向其他正在连接的客户端宣告`client2`子网的存在。 最后一步,这也是经常被忘记的一步:在服务器的局域网网关处添加一个路由,用以将`192.168.4.0/24`定向到 OpenVPN 服务器(如果 OpenVPN 服务器和局域网网关在同一计算机上,则无需这么做)。假设缺少了这一步,当你从`192.168.4.8`向服务器局域网的某台计算机发送`ping`命令时,这个外部 ping 命令很可能能够到达目标计算机,但是却不知道如何路由一个`ping`回复,因为它不知道如何达到`192.168.4.0/24`。主要的使用规则是:当全部的局域网都通过 VPN 时(并且 OpenVPN 服务器和局域网网关不在同一计算机),请确保在局域网网关处将所有的 VPN 子网都路由到 VPN 服务器所在计算机。 类似地,如果 OpenVPN 客户端和客户端局域网网关不在同一计算机上,请在客户端局域网网关处创建路由,以确保通过 VPN 的所有子网都能转向 OpenVPN 客户端所在计算机。 笔者注:上面的看得有点晕,简单介绍下**添加路由**的几种方式: * 在网关添加路由。如在`10.66.0.0/24`网关处添加一条访问`192.168.4.0/24`时以`10.66.0.5`为网关,在`192.168.4.0/24`网关处添加一条访问`10.66.0.0/24`时以`192.168.4.10`为网关。 * 在其他终端上添加路由表。(服务器所在网段的)Windows 如下添加:`route add 192.168.4.0 mask 255.255.255.0 10.66.0.5`,(客户端所在网段的)Windows 如下添加:`route add 10.66.0.0 mask 255.255.255.0 192.168.4.10`,如果添加永久路由,使用`-p`参数。其它系统的自行网上找资料。 * (客户端所在网段的)Windows 需要添加:`route add 10.8.0.0 mask 255.255.255.0 192.168.4.10`,才能被服务器(或服务器所在网段的其他电脑)访问到。 * 可以综合参考以上方式,来控制加入此互访网络的终端。 ### [](#191-防火墙规则)1.9.1. 防火墙规则 基于路由模式(`dev tun`)时,OpenVPN 服务器上防火墙配置(主要是关于防火墙如何工作,熟悉的可以略过了)简要归纳(开放监听端口不在此赘述): 假设环境如下: 服务端网段`10.66.0.0/24`下设备:OpenVPN 服务器 IP 地址`10.66.0.5`,A 服务器(Windows)IP 地址`10.66.0.33` OpenVPN 虚拟 IP 网段`10.8.0.0/24` 客户端网段`192.168.4.0`下设备:OpenVPN 客户端 IP 地址`192.168.4.10`,X 终端(Windows)IP 地址`192.168.4.66` 1、防火墙不添加任何设置: 只能客户端与服务器互相访问(两者正常情况都可以互相访问,下面不再单独说明,以下所有访问指的使用`ping`测试通过,测试时 Windows 系统注意关闭防火墙或者设置规则允许 ICMP 协议入站) 2、防火墙设置: ``` *filter # 允许进tun接口目标为“10.8.0.0/24”的访问 -A FORWARD -o tun+ -d 10.8.0.0/24 -j ACCEPT # “+”也可改为实际的“tun[n]”,如“tun0”、“tun1”... # 允许源为“10.8.0.0/24”出tun接口的访问 -A FORWARD -i tun+ -s 10.8.0.0/24 -j ACCEPT # 如果需要设置指定可以访问的服务器范围,删除上面一行,如下设置 -A FORWARD -i tun+ -s 10.8.0.0/24 -d 10.66.0.33 -j ACCEPT # OpenVPN客户端不能访问到除10.66.0.33外其他的服务器(如果存在) ``` 无其它设置时还是只能客户端与服务器互相访问,在 A 服务器添加路由表:`route add 10.8.0.0 mask 255.255.255.0 10.66.0.5`(或在服务器网关处添加类似路由,以下所有路由表都可以在网关处添加来替换该步骤,只不过作用范围不同,下面不再单独说明), OpenVPN 客户端和 A 服务器可以互相访问 3、防火墙设置: ``` *nat # 添加下面一行,OpenVPN服务器可访问的地址,客户端也可以访问 -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE # 或如下设置指定网卡(若添指定了网卡,那么OpenVPN服务器自身通过该网卡不能访问的地址,客户端也不能访问) -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE *filter -A FORWARD -o tun+ -d 10.8.0.0/24 -j ACCEPT -A FORWARD -i tun+ -s 10.8.0.0/24 -j ACCEPT ``` 无其它设置时 OpenVPN 客户端可以访问到 A 服务器,A 服务器访问不到 OpenVPN 客户端,在 A 服务器添加路由表:`route add 10.8.0.0 mask 255.255.255.0 10.66.0.5`,OpenVPN 客户端和 A 服务器可以互相访问 **小结**: 要客户端与服务器所在网段其他设备互相访问需要的防火墙设置为: ``` *nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE # 可视实际情况(如配置了路由表或是网关配置了路由)选择不配置 *filter -A FORWARD -o tun+ -d 10.8.0.0/24 -j ACCEPT -A FORWARD -i tun+ -s 10.8.0.0/24 -j ACCEPT -A FORWARD -i tun+ -s 10.8.0.0/24 -d 10.66.0.33 -j ACCEPT # 此规则与上一行选一种来使用 ``` firewalld 对应命令: ``` firewall-cmd --zone=block --add-interface=tun+ firewall-cmd --permanent --zone=block --add-interface=tun+ firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 -j MASQUERADE firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -o tun+ -d 10.8.0.0/24 -j ACCEPT firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i tun+ -s 10.8.0.0/24 -j ACCEPT firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i tun+ -s 10.8.0.0/24 -m iprange --dst-range 10.66.0.33-10.66.0.50 -j ACCEPT # 或是指定允许访问的范围 # --direct不能使用--permanent,即使没有报错,重启服务或服务器后,对应的命令也不会生效 ``` 如果对 tun 接口的所有流量都允许,可最简(最宽松的防火墙设置,不建议,可根据具体使用场景来综合考虑使用配置)为: ``` *nat -A POSTROUTING -j MASQUERADE *filter -A FORWARD -o tun+ -j ACCEPT -A FORWARD -i tun+ -j ACCEPT ``` 以下内容假设服务器已按 “包含基于路由模式的 VPN 客户端的多台计算机” 步骤配置好服务器和客户端(除开 OpenVPN 服务器防火墙相关内容): 4、防火墙设置: ``` *filter -A FORWARD -o tun+ -d 10.8.0.0/24 -j ACCEPT -A FORWARD -i tun+ -s 10.8.0.0/24 -j ACCEPT -A FORWARD -o tun+ -d 192.168.4.0/24 -j ACCEPT -A FORWARD -i tun+ -s 192.168.4.0/24 -j ACCEPT # 同样可以加入类似“-d 10.66.0.33”对允许访问的服务器进行限制 ``` 无其它设置时还是只能客户端与服务器互相访问,在 A 服务器添加路由表:`route add 192.168.4.0 mask 255.255.255.0 10.66.0.5`,在 X 终端添加路由表:`route add 10.66.0.0 mask 255.255.255.0 192.168.4.10`, OpenVPN 客户端、X 终端、OpenVPN 服务器及 A 服务器可以互相访问 5、一些其他测试: ``` *filter -A FORWARD -o tun+ -d 192.168.4.0/24 -j ACCEPT -A FORWARD -i tun+ -s 192.168.4.0/24 -j ACCEPT ``` 去掉了关于`10.8.0.0/24`的内容,只要添加好了路由表,各设备之间还是可以通过真实局域网 IP 地址来访问 如果想客户端在服务端的设备不加路由表的情况(单向)访问各服务器,加入: ``` -A POSTROUTING -s 192.168.4.0/24 -j MASQUERADE ``` 同样如果对 tun 接口的所有流量都允许,可以简化为: ``` *filter -A FORWARD -o tun+ -j ACCEPT -A FORWARD -i tun+ -j ACCEPT ``` [](#110-推送dhcp选项到客户端)1.10. 推送 DHCP 选项到客户端 ----------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#dhcp) OpenVPN 服务器能够推送诸如 DNS、WINS 服务器地址等 DHCP 选项参数到客户端(这里是一些值得注意的[附加说明](https://community.openvpn.net/openvpn/wiki/FAQ#dhcpcaveats))。Windows 客户端原生就能够接受被推送来的 DHCP 选项参数,但非 Windows 系统的客户端需要使用客户端的 up 脚本才能接受它们,`up`脚本能够解析`foreign_option_n`环境变量列表。请进入[手册页面](https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html)或者 [OpenVPN 用户的邮件列表档案](https://openvpn.net/index.php/open-source/documentation/miscellaneous/61-mailing-lists.html)查看非 Windows 系统的`foreign_option_n`文档和脚本示例。 举个例子,假如你希望正在连接的客户端使用一个内部的 DNS 服务器`10.66.0.4`或`10.66.0.5`,和一个 WINS (赢) 服务器`10.66.0.8`,在 OpenVPN 服务器配置中添加下列语句: ``` push "dhcp-option DNS 10.66.0.4" push "dhcp-option DNS 10.66.0.5" push "dhcp-option WINS 10.66.0.8" ``` 想要在 Windows 上测试该功能,在客户端连接 OpenVPN 服务器后,在命令提示符中运行如下命令: ``` ipconfig -all ``` 其中,“TAP-Windows” 部分应该显示服务器推送过来的 DHCP 选项参数。 [](#111-为指定客户端配置规则和访问策略)1.11. 为指定客户端配置规则和访问策略 --------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#policy) 经测试,服务端使用`topology subnet`,原文的方式不能使用,可以使用下面示例来分配指定的 IP: ``` ;server 10.8.0.0 255.255.255.0 mode server tls-server push "topology subnet" ifconfig 10.8.0.1 255.255.255.0 ifconfig-pool 10.8.0.50 10.8.0.100 255.255.255.0 push "route-gateway 10.8.0.1" ``` CCD 配置文件: ``` ifconfig-push 10.8.0.10 255.255.255.0 ``` 假设,创建了一个供企业使用的 VPN,想要分别为 3 种不同级别的用户单独设置访问策略: * 系统管理员 -- 允许访问网络内的所有终端 * 普通职工 -- 只允许访问 Samba/Email 服务器 * 承包商 -- 只允许访问特定的服务器 所要采取的基本方法是: * 给不同级别的用户划分不同的虚拟 IP 地址范围 * 通过设置锁定客户端虚拟 IP 地址的防火墙规则来控制对计算机的访问。 本例中假设有大量的普通职工,只有 1 个系统管理员、2 个承包商。IP 配置方案将会把所有的普通职工放入一个 IP 地址池中,然后为系统管理员和承包商分配固定的 IP 地址。 注意:本例的前提条件之一就是有一个运行于 OpenVPN 服务器所在计算机上的软件防火墙,并具备自定义防火墙规则的能力。这里假定防火墙是 Linux 系统的 iptables。 首先,根据用户级别创建一个虚拟 IP 地址映射: <table><thead><tr><th>Class</th><th><relin-hc><relin-highlight data-word="Virtual"><relin-origin>Virtual</relin-origin> <relin-target>(虚拟)</relin-target> </relin-highlight>IP <relin-highlight data-word="Range"><relin-origin>Range</relin-origin> <relin-target>(范围)</relin-target></relin-highlight></relin-hc></th><th><relin-hc><relin-highlight data-word="Allowed"><relin-origin>Allowed</relin-origin> <relin-target>(允许)</relin-target> </relin-highlight>LAN <relin-highlight data-word="Access"><relin-origin>Access</relin-origin> <relin-target>(访问)</relin-target></relin-highlight></relin-hc></th><th><relin-hc><relin-highlight data-word="Common"><relin-origin>Common</relin-origin> <relin-target>(常见)</relin-target> </relin-highlight>Names</relin-hc></th></tr></thead><tbody><tr><td>普通职工</td><td>10.8.0.0/24</td><td>Samba/Email 服务器为 10.66.4.4</td><td>[数量众多]</td></tr><tr><td>系统管理员</td><td>10.8.1.0/24</td><td>10.66.4.0/24 整个网段</td><td>sysadmin1</td></tr><tr><td>承包商</td><td>10.8.2.0/24</td><td>承包商服务器为 10.66.4.12</td><td>contractor1, contracter2</td></tr></tbody></table> 下一步,将上述映射转换到 OpenVPN 服务器配置中。首先确保已经遵循了[上述步骤](#19-%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%88%96%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%AD%90%E7%BD%91%E4%B8%AD%E7%9A%84%E5%85%B6%E4%BB%96%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BA%92%E7%9B%B8%E8%AE%BF%E9%97%AE)并将`10.66.4.0/24`网段分配给了所有的客户端(虽然配置允许客户端访问整个`10.66.4.0/24`网段,不过稍后将利用防火墙规则强制添加访问限制来实现上述表格中的访问策略)。 首先,为 tun 接口定义一个静态的单元编号,以便于稍后在防火墙规则中使用它: ``` dev tun0 ``` 在服务器配置文件中,定义普通职工的 IP 地址池: ``` server 10.8.0.0 255.255.255.0 ``` 为系统管理员和承包商的 IP 范围添加路由: ``` # 管理员的IP范围 route 10.8.1.0 255.255.255.0 # 承包商的IP范围 route 10.8.2.0 255.255.255.0 ``` 因为要为指定的系统管理员和承包商分配固定的 IP 地址,将使用一个客户端配置文件: ``` client-config-dir ccd ``` 在`ccd`子目录中放置专用的配置文件,为每个非普通职工的 VPN 客户端定义固定的 IP 地址。 文件`ccd/sysadmin1`: ``` ifconfig-push 10.8.1.1 10.8.1.2 ``` 文件`ccd/contractor1`: ``` ifconfig-push 10.8.2.1 10.8.2.2 ``` 文件`ccd/contractor2`: ``` ifconfig-push 10.8.2.5 10.8.2.6 ``` `ifconfig-push`中的每一对 IP 地址表示虚拟客户端和服务器的 IP 端点。它们必须从连续的`/30`子网网段中获取(这里是`/30`表示`xxx.xxx.xxx.xxx/30`,即子网掩码位数为 30),以便于与 Windows 客户端和 TAP-Windows 驱动兼容。明确地说,每个端点的 IP 地址对的最后 8 位字节必须取自下面的集合: ``` [ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18] [ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38] [ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58] [ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78] [ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98] [101,102] [105,106] [109,110] [113,114] [117,118] [121,122] [125,126] [129,130] [133,134] [137,138] [141,142] [145,146] [149,150] [153,154] [157,158] [161,162] [165,166] [169,170] [173,174] [177,178] [181,182] [185,186] [189,190] [193,194] [197,198] [201,202] [205,206] [209,210] [213,214] [217,218] [221,222] [225,226] [229,230] [233,234] [237,238] [241,242] [245,246] [249,250] [253,254] ``` 完成了 OpenVPN 的配置,最后一步是添加防火墙规则来完成访问策略。下例使用 Linux 系统 iptables 语法的防火墙规则: ``` # 普通职工规则 iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d 10.66.4.4 -j ACCEPT # 系统管理员规则 iptables -A FORWARD -i tun0 -s 10.8.1.0/24 -d 10.66.4.0/24 -j ACCEPT # 承包商规则 iptables -A FORWARD -i tun0 -s 10.8.2.0/24 -d 10.66.4.12 -j ACCEPT ``` [](#112-使用其他身份验证方式)1.12. 使用其他身份验证方式 ----------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#auth) OpenVPN 2.0 及以上版本支持 OpenVPN 服务器安全地从客户端获取用户名和密码,并以该信息作为客户端身份验证的基础。 使用该身份验证方式,先在客户端配置中添加`auth-user-pass`指令。这使得 OpenVPN 客户端直接向用户询问用户名 / 密码,并通过安全的 TLS 隧道将其传递到服务器。 下一步,配置服务器以使用一个身份验证插件,该插件可以是一个脚本、共享的对象或者 DLL 文件。在每次客户端尝试连接时,OpenVPN 服务器就会调用该插件,并将客户端输入的用户名 / 密码传递给它。身份验证插件通过返回一个表示失败 (1) 或成功 (0) 的值,从而控制 OpenVPN 是否允许该客户端连接。 **使用脚本插件** 通过在服务器端配置文件中添加`auth-user-pass-verify`指令,可以使用脚本插件。例如: ``` auth-user-pass-verify auth-pam.pl via-file ``` 将使用名为`auth-pam.pl`的 perl 脚本来验证正在连接的客户端的用户名 / 密码。详情请查看[手册页面](https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html)中关于`auth-user-pass-verify`的相关描述。 `auth-pam.pl`脚本文件位于 OpenVPN 源代码发行版的`sample-scripts`子目录中。在 Linux 服务器上,它将使用 PAM 认证模块对用户进行身份验证,从而实现 shadow 密码、RADIUS(远程用户拨入验证服务)或者 LDAP(轻量级目录访问协议)验证。`auth-pam.pl`主要用于演示目的。对于实际的 PAM 验证,请使用下面描述的`openvpn-auth-pam`共享对象插件。 **使用共享对象或 DLL 插件** 共享对象或 DLL 插件通常是一个经过编译的 C 模块,它能够在运行时被 OpenVPN 服务器加载。如果在 Linux 系统中使用基于 RPM 的 OpenVPN,`openvpn-auth-pam`插件应该已经创建好了。为了使用该插件,在服务器端配置文件中添加如下语句: ``` plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login ``` 这将告诉 OpenVPN 服务器使用 login PAM 模块来校验客户端输入的用户名 / 密码。 对于实际生产环境中,最好使用`openvpn-auth-pam`插件,因为相对使用`auth-pam.pl`脚本而言,它具有以下几个优点: * 共享对象`openvpn-auth-pam`插件采用更加安全的拆分权限执行模式。这意味着 OpenVPN 服务器可以运行在使用`user nobody`、`group nobody`和`chroot`等指令来降低权限的情况下,并且能够进行身份验证,而不依赖于只有 root 用户才能读取的 shadow 密码文件。 * OpenVPN 可以通过虚拟内存将用户名 / 密码传递给插件,而不是通过一个文件或环境变量,对于服务器计算机而言,具有更好的本地安全性。 如果想了解更多关于开发自己的插件以便与 OpenVPN 一起使用的信息,请参阅 OpenVPN 源代码发行版`plugin`子目录中的`README`文件。 在 Linux 中,为了构建`openvpn-auth-pam`插件,请转到 OpenVPN 源代码发行版的`plugin/auth-pam`目录,并运行`make`。 **使用用户名 / 密码认证作为唯一的客户端认证形式** 默认情况下,在服务器上使用`auth-user-pass-verify`或者用户名 / 密码验证插件将会启用双重身份验证,这使得待验证客户端的客户端证书和用户名 / 密码验证都必须通过。 也可以禁用客户端证书,而强制只使用用户名 / 密码验证(从安全角度来说,不鼓励这样做)。在服务器端加入: ``` client-cert-not-required ``` 通常还需要这样设置: ``` username-as-common-name ``` 这将告诉服务器优先使用用户名,就像它使用那些通过客户端证书认证的客户端的 Common (常见) Name 一样 (也就是说,使用 username 作为 Common Name,用法与之前使用 Common Name 时相同)。 注意:`client-cert-not-required`并不排除对服务器证书的需要,所以一个客户端连接到使用了`client-cert-not-required`指令的服务器,可以删除客户端配置文件中的`cert`和`key`指令,但不能删除`ca`指令,因为它对于客户端验证服务器端证书来说是必需的。 [](#113-使用客户端的智能卡实现双重认证)1.13. 使用客户端的智能卡实现双重认证 --------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#pkcs11) [](#114-路由所有客户端流量通过vpn)1.14. 路由所有客户端流量通过 VPN -------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#redirect) **概述** 默认情况下,当一个 OpenVPN 客户端处于活动状态时,只有往返于 OpenVPN 服务器的网络流量才会通过 VPN。如一般的网页浏览操作,将绕过 VPN,直接连接来完成。 在某些情况下,可能想让 VPN 客户端所有的网络流量均通过 VPN,也包括一般的网络流量。虽然客户端的这种 VPN 配置将会耗费一些性能,但在客户端同时连接公共网络和 VPN 时,它给 VPN 管理员在安全策略上更多的控制能力。 **实施** 在服务器配置文件中添加如下指令: ``` push "redirect-gateway def1" ``` 如果 VPN 安装在无线网络上,并且 OpenVPN 服务器和客户端均处于同一个无线子网中,请添加`local`标记: ``` push "redirect-gateway local def1" ``` 推送`redirect-gateway`选项命令到客户端,将会导致源自客户端计算机的所有 IP 网络流量通过 OpenVPN 服务器。服务器需要进行配置,从而以某种方式处理这些流量,例如:通过 NAT 转化流量到 internet,或者路由通过服务器所在网络场所的 HTTP 代理。在 Linux 系统中,你可以使用如下命令将 VPN 客户端的流量 NAT 转化到 internet: ``` iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE ``` 该命令假定 VPN 子网网段为`10.8.0.0/24`(取自 OpenVPN 服务器配置的 server 指令),本地以太网接口为 eth0。 当启用了`redirect-gateway`指令,OpenVPN 客户端将路由所有的 DNS 查询经过 VPN,VPN 服务器需要处理掉这些查询。在 VPN 活动期间,我们可以通过推送 DNS 服务器地址到正在连接的客户端上来完成该操作,从而代替常规的 DNS 服务器设置: ``` push "dhcp-option DNS 10.8.0.1" ``` 这将配置 Windows 客户端(或带有额外的服务器端脚本的非 Windows 客户端)使用`10.8.0.1`作为它们的 DNS 服务器。任何客户端能够到达的地址都可能作为 DNS 服务器。 **注意事项** 通过 VPN 重定向所有网络流量并不是完全没有问题的提议。以下是一些典型的疑难问题: * 多数连接 internet 的 OpenVPN 客户端计算机会定期与 DHCP 服务器进行交互,并更新它们的 IP 地址租约。`redirect-gateway`选项命令可能会阻止客户端连接到本地 DHCP 服务器(因为 DHCP 信息会被路由通过 VPN),从而导致丢失 IP 地址租约。 * 关于推送 DNS 地址到 Windows 客户端[存在一些问题](https://community.openvpn.net/openvpn/wiki/FAQ#dhcpcaveats)。 * 客户端的 Web 浏览性能将会明显降低。 关于`redirect-gateway`指令的更多信息,请参考[手册页面](https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html)。 [](#115-在动态ip地址上运行openvpn服务器)1.15. 在动态 IP 地址上运行 OpenVPN 服务器 ----------------------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#dynamic) 总结一句就是使用动态域名解析 [](#116-通过http代理连接openvpn服务器)1.16. 通过 HTTP 代理连接 OpenVPN 服务器 ----------------------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#http) OpenVPN 支持以下列身份认证方式通过 HTTP 代理进行连接: * 无需代理身份认证 * 基本 ( Basic (基本) ) 代理身份认证 * NTLM 代理身份认证 首先,HTTP 代理的用法要求你必须使用 TCP 协议作为隧道载体。所以,在客户端和服务器配置中均添加如下语句: ``` proto tcp ``` 确保删除(或注释)配置文件中的所有`proto udp`指令行。 下一步,在客户端配置文件中添加`http-proxy`指令(请查看[手册页面](http://openvpn.net/man.html)了解该指令的详细描述信息)。 例如,假设客户端局域网有一台`192.168.4.1`的 HTTP 代理服务器,并监听在`1080`端口。在客户端配置中添加如下语句: 假设 HTTP 代理要求基本的身份认证: ``` http-proxy 192.168.4.1 1080 stdin basic ``` 假设 HTTP 代理要求 NTLM 身份认证: ``` http-proxy 192.168.4.1 1080 stdin ntlm ``` 上面的两个身份认证示例将会使 OpenVPN 提示从标准输入界面输入用户名 / 密码。如果希望将这些用户凭据放入一个文件中来代替上述输入操作,使用一个文件名来替换语句中的 stdin,该文件的第 1 行应该放用户名,第 2 行放密码。 [](#117-通过openvpn连接samba网络共享服务器)1.17. 通过 OpenVPN 连接 Samba 网络共享服务器 ----------------------------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#samba) 本示例演示 OpenVPN 是如何通过基于路由的`dev tun`隧道连接到一个 Samba 共享服务器的。如果使用的是以太网桥接模式 (`dev tap`),你可能不需要遵循下列操作,因为 OpenVPN 客户端可以在网络邻居中看到服务器端局域网中的计算机。 在本例中假设: * 服务器端局域网使用子网网段`10.66.0.0/24` * VPN IP 地址池使用`10.8.0.0/24`(作为 OpenVPN 服务器配置文件中的 server 指令参数) * Samba 服务器的 IP 地址为`10.66.0.4` * Samba 服务器已进行配置,从本地局域网能够正常访问 如果 Samba 和 OpenVPN 服务器运行于不同的计算机,请确保已经遵循并实现了[扩大 OpenVPN 使用范围,包含服务器或客户端子网中的其他计算机](#19-%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%88%96%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%AD%90%E7%BD%91%E4%B8%AD%E7%9A%84%E5%85%B6%E4%BB%96%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%BA%92%E7%9B%B8%E8%AE%BF%E9%97%AE)。 下一步,编辑 Samba 配置文件 (`smb.conf`)。确保`hosts allow`指令允许来自`10.8.0.0/24`网段的 OpenVPN 客户端进行连接。例如: ``` hosts allow = 10.66.0.0/24 10.8.0.0/24 127.0.0.1 ``` 如果 Samba 和 OpenVPN 服务器运行于同一台计算机,可以编辑`smb.conf`文件中的`interfaces`指令,也监听 TUN 接口网段`10.8.0.0/24`: ``` interfaces = 10.66.0.0/24 10.8.0.0/24 ``` 如果 Samba 和 OpenVPN 服务器运行于同一台计算机,使用文件夹名称: ``` \\10.8.0.1\\sharename ``` 如果 Samba 和 OpenVPN 服务器位于不同的计算机,使用文件夹名称: ``` \\10.66.0.4\sharename ``` 例如,从命令提示符窗口中运行: ``` net use z: \\10.66.0.4\sharename /USER:myusername ``` [](#118-实现负载均衡故障转移的配置)1.18. 实现负载均衡 / 故障转移的配置 -------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#loadbalance) **客户端配置** OpenVPN 客户端配置可以用于实现负载均衡和故障转移功能的多台服务器。例如: ``` remote server1.mydomain remote server2.mydomain remote server3.mydomain ``` 这将指示 OpenVPN 客户端按照顺序尝试与 server1、server2、server3 进行连接。如果现有的连接被中断,OpenVPN 客户端将会重新尝试连接最近连接过的服务器;如果连接失败,客户端将会尝试与列表中的下一个服务器进行连接(测试大致会尝试半分钟至 1 分钟左右后,连接下一个服务器)。也可以指示 OpenVPN 客户端在启动时随机连接列表中的一个服务器,以便于客户端负载能够均等概率地覆盖服务器池。 ``` remote-random ``` 如果也希望在 DNS 解析失败时,让 OpenVPN 客户端移至列表中的下一个服务器,添加如下命令: ``` resolv-retry 60 ``` 参数`60`告诉 OpenVPN 客户端,在移至下一个服务器之前,尝试解析每个`remote`的 DNS 名称 60 秒(即 60 秒内都无法解析成功,就移至下一个服务器)。 服务器列表还可以引用运行于同一计算机上的多个 OpenVPN 服务器进程(每个进程监听不同的端口),例如: ``` remote smp-server1.mydomain 8000 remote smp-server1.mydomain 8001 remote smp-server2.mydomain 8000 remote smp-server2.mydomain 8001 ``` 如果服务器有多个处理器,每台计算机运行多个 OpenVPN 后台进程有利于提高性能表现。 OpenVPN 也支持`remote`指令引用在域名配置中拥有多个 A 记录的 DNS 名称。在这种情况下,在每次域名被解析时,OpenVPN 客户端将会随机选择一个 A 记录。 **服务器端配置** 除了每个服务器使用不同的虚拟 IP 地址池之外,为集群中的每个服务器使用相同的配置文件,是在服务器端实现负载均衡 / 故障转移配置的最简单方法。例如: server1: ``` server 10.8.0.0 255.255.255.0 ``` server2: ``` server 10.8.1.0 255.255.255.0 ``` server3: ``` server 10.8.2.0 255.255.255.0 ``` [](#119-增强openvpn的安全性)1.19. 增强 OpenVPN 的安全性 ------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#security) 一个经常被重复提及的网络安全准则就是:不要过分相信一个单一的安全组件,否则它的失败将导致灾难性的安全漏洞。OpenVPN 提供多种机制来添加额外的安全层,以避免这样的结果。 **tls-auth** `tls-auth`指令为所有的 SSL/TLS 握手数据包添加一个额外的 HMAC 签名,以验证数据的完整性。无需进一步处理,没有正确的 HMAC 签名的任何 UDP 数据包将会被丢弃。`tls-auth` HMAC 签名提供了上面所说的额外安全级别,而不是通过 SSL/TLS 来提供。它可以防御: * Dos 攻击或者 UDP 端口淹没攻击。 * 确定服务器 UDP 端口监听状态的端口扫描。 * SSL/TLS 实现的缓冲区溢出漏洞。 * 启动来自未经授权机器的 SSL/TLS 握手(虽然这样的握手最终会验证失败,但`tls-auth`可以更早地断开)。 除了使用标准的 RSA 证书 / 密钥之外,使用`tls-auth`还需要生成一个共享的密钥: ``` openvpn --genkey --secret ta.key ``` 该命令将生成一个 OpenVPN 静态密钥,并将其写入到`ta.key`文件中。该密钥应该通过已有的安全通道拷贝到服务器和所有的客户端。它应该与 RSA 的`.key`和`.crt`文件放在同一目录。 在服务器配置中,添加: ``` tls-auth ta.key 0 ``` 在客户端配置中,添加: ``` tls-auth ta.key 1 ``` **proto udp** 虽然 OpenVPN 允许使用 TCP 或者 UDP 协议作为 VPN 的连接载体,但 UDP 协议能够比 TCP 提供更好的 Dos 攻击和端口扫描防护: ``` proto udp ``` **user/group(仅限于非 Windows 系统)** OpenVPN 经过非常仔细的设计,以允许在初始化后丢弃掉 root 权限,该特性可以在 Linux/BSD/Solaris 系统中一直使用。 对于攻击者而言,没有 root 权限,运行中的 OpenVPN 服务器进程就不是一个有吸引力的目标。 ``` user nobody group nobody ``` **非特权模式(仅限于 Linux 系统)** 在 Linux 系统中,OpenVPN 可以完全没有特权地正常运行。虽然配置上会稍稍麻烦一点,但却能带来最佳的安全性。 为了使用这种配置来运行,OpenVPN 必须配置为使用`iproute`接口,这可以通过为`configure`脚本指定`--enable-iproute2`参数来完成。系统也需要有`sudo`软件包。 该配置使用 Linux 自身的能力来更改 tun 设备的权限,以便于非特权的用户也可以访问它。为了执行`iproute`,也需要使用`sudo`,从而使得接口属性和路由表可以被修改。 OpenVPN 配置: * 重写并覆盖位于`/usr/local/sbin/unpriv-ip`的以下脚本文件: ``` #!/bin/sh sudo /sbin/ip $* ``` * 执行`visudo`,添加如下命令以允许用户 "user1" 执行`/sbin/ip`: ``` user1 ALL=(ALL) NOPASSWD: /sbin/ip ``` 也可以通过如下命令启用一个用户组: ``` %users ALL=(ALL) NOPASSWD: /sbin/ip ``` * 在 OpenVPN 配置中添加如下语句: ``` dev tunX/tapX iproute /usr/local/sbin/unpriv-ip ``` 注意:必须选择常量 X(一般用数字标记,例如:tunX 实际为 tun0),并且不能同时指定 tun 或 tap。 * 使用 root (根) 添加持久化接口,允许用户或用户组来管理它,下面的命令会创建`tunX`,并且允许 user1 和用户组访问它: ``` openvpn --mktun --dev tunX --type tun --user user1 --group users ``` * 在非特权用户的上下文环境中运行 OpenVPN。 可以通过核查脚本文件`/usr/local/sbin/unpriv-ip`的参数来添加进一步的安全约束。 **chroot(仅限于非 Windows 系统)** `chroot`指令允许将 OpenVPN 后台进程锁定到所谓的`chroot jail`(chroot 监狱)中,除了该指令参数给出的指定目录外,`chroot jail`中的进程无法访问主机系统的文件系统的任何部分。例如: ``` chroot jail ``` 将导致 OpenVPN 进程在初始化时转到 jail 子目录,然后将它的根文件系统调整为该目录,进程将无法访问 jail 和它的子目录树以外的任何文件。从安全角度来说,这很重要,因为即使攻击者能够使用代码插入攻击入侵服务器,攻击也会被锁定在服务器的大部分文件系统之外。 注意事项:由于 chroot 调整了文件系统(仅从后台进程的角度来看),因此有必要将 OpenVPN 初始化后可能用到的文件放入 jail 目录中,例如: * 文件`crl-verify` * 或者目录`client-config-dir` **更大的 RSA 密钥** 我们可以通过文件`easy-rsa/vars`中的`KEY_SIZE`变量来控制 RSA 密钥的大小,该变量必须在所有密钥生成之前进行设置。如果默认设置为`1024`,可以合理地提高到`2048`,这对 VPN 隧道的性能没有什么负面影响,除了稍稍减缓每个客户端每小时一次的 SSL/TLS 重新协商握手速度,和大幅减慢使用脚本`easy-rsa/build-dh`生成迪菲赫尔曼参数的一次性过程之外。 **更大的对象密钥** 默认情况下,OpenVPN 使用 128 位对称加密算法`Blowfish`。 OpenVPN 自动支持 OpenSSL 库支持的任何加密算法,同样支持使用更大密钥长度的加密算法。例如,通过在服务器和客户端配置文件中均添加如下语句来使用 256 位版本的 AES(Advanced Encryption Standard (标准) ,高级加密标准): ``` cipher AES-256-CBC ``` **将根密钥(`ca.key`)保留在一台没有网络连接的计算机上** 使用 X509 PKI(OpenVPN 也使用)的安全好处之一就是,根 CA 密钥(`ca.key`)不需要放在当前 OpenVPN 服务器所在计算机上。在一个高度安全的环境中,可以特别指定一台计算机用于密钥签名,让该计算机受到良好的保护,并断开所有的网络。必要时,可以使用软盘(这个可能已经绝迹了吧)来回移动该密钥文件。这些措施使得攻击者想要窃取根密钥变得非常困难(对于密钥签名计算机的物理盗窃除外)。 [](#120-撤销证书)1.20. 撤销证书 ----------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#revoke) **撤销一个证书**就是让一个已签名的证书作废,以便其无法再用于身份认证。 想要撤销一个证书的典型原因包括: * 与证书关联的私钥被泄露或被窃取。 * 加密私钥的用户忘记了密码。 * 你想要终止某个 VPN 用户的访问。 例如撤销证书`client2`,该证书是前面的操作指南的 “[生成密钥](#14-%E5%88%9B%E5%BB%BA%E8%AF%81%E4%B9%A6)” 部分生成的。 首先,打开 shell (壳) 或命令提示符窗口,转到之前 “生成密钥” 部分操作过的`easy-rsa`目录。在 Linux/BSD/Unix 系统中: ``` . ./vars ./revoke-full client2 ``` 在 Windows 系统中: ``` vars revoke-full client2 ``` 可以看到类似这样的输出: ``` Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf DEBUG[load_index]: unique_subject = "yes" Revoking Certificate 04. Data Base Updated Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf DEBUG[load_index]: unique_subject = "yes" client2.crt: /C=KG/ST=NA/O=OpenVPN-TEST/CN=client2/emailAddress=me@myhost.mydomain error 23 at 0 depth lookup:certificate revoked ``` 注意最后一行的`error 23`表明已被撤销的证书的证书校验失败(即撤销成功)。 `revoke-full`脚本将会在`keys`子目录中生成一个叫做`crl.pem`的 CRL(证书撤销列表)文件。该文件应该被复制到一个 OpenVPN 服务器可以访问的目录,然后在服务器配置中启用 CRL 验证: ``` crl-verify crl.pem ``` 现在,所有正在连接的客户端的证书会与 CRL 进行比对校验,任何正匹配都将导致该连接被丢失。 **CRL 注意事项** * 当 OpenVPN 使用`crl-verify`选项命令后,任何新的客户端连接或者现有客户端重新建立 SSL/TLS 连接(默认每小时一次)都将使得 CRL 文件被重新读取。这意味着,即使 OpenVPN 服务器后台进程正在运行,你也可以更新你的 CRL 文件,新的 CRL 文件将会对新连接的客户端直接生效。如果一个刚刚撤销了证书的客户端早已经连接到服务器,你可以通过一个信号(SIGUSR1 或者 SIGHUP)来重启服务器,并刷新所有的客户端,或者你可以远程登录[管理接口](https://openvpn.net/management.html),明确杀掉服务器上指定的客户端实例对象,而不干扰其他客户端。 * 虽然 OpenVPN 服务器和客户端都可以使用`crl-verify`指令,但通常不必将 CRL 文件分发到客户端,除非服务器证书已被撤销。客户端不需要知道其他哪些客户端的证书已被撤销,因为[客户端不应该直接接受来自其他客户端的连接](#121-%E5%85%B3%E4%BA%8E%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB%E7%9A%84%E9%87%8D%E8%A6%81%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9)。 * CRL 文件无需保密,并且应该设为所有用户可读,以便于 OpenVPN 进程在没有 root 权限的情况下能够读取该文件。 * 如果使用`chroot`指令,请确保在`chroot`目录放置一份 CRL 文件的拷贝,因为不像 OpenVPN 读取的其他大多数文件,CRL 将会在执行`chroot`调用之后被读取,而不是在此之前。 * 需要撤销证书的一个常见原因是,用户使用密码加密了自己的私钥,然后忘记了密码。通过撤销原来的证书,用户也可以使用原来的`Common Name`来生成新的证书 / 密钥对。 [](#121-关于中间人攻击的重要注意事项)1.21. 关于中间人攻击的重要注意事项 ------------------------------------------- [英文原文](https://openvpn.net/index.php/open-source/documentation/howto.html#secnotes) 如果客户端不验证他们正在连接的服务器的证书,可能的 “中间人” 攻击。 为了避免授权客户端通过冒充的服务器尝试连接到另一个客户端的可能的中间人攻击,务必强制客户端进行某种类型的服务器证书验证。目前有五种不同的方式来完成这一点,按优先顺序排列: * **OpenVPN 2.1 及以上版本**使用指定的密钥用法和扩展密钥用法来创建服务器证书。RFC3280 确定了应该为 TLS 连接提供下列属性: <table><thead><tr><th>模式</th><th>密钥用法</th><th>扩展密钥用法</th></tr></thead><tbody><tr><td>客户端</td><td>数字签名</td><td>TLS Web 客户端认证</td></tr><tr><td>客户端</td><td>密钥协议</td><td>TLS Web 客户端认证</td></tr><tr><td>客户端</td><td>数字签名,密钥协议</td><td>TLS Web 客户端认证</td></tr><tr><td>服务器</td><td>数字签名,密钥加密</td><td>TLS Web 服务器认证</td></tr><tr><td>服务器</td><td>数字签名,密钥协议</td><td>TLS Web 服务器认证</td></tr></tbody></table> 可以使用`build-key-server`脚本来创建服务器证书(详情请查看 [easy-rsa](https://openvpn.net/easyrsa.html) 文档)。通过设置正确的属性,指定证书作为一个服务器端证书。在客户端配置中添加如下语句: ``` remote-cert-tls server ``` * **OpenVPN 2.0 及以下版本**使用`build-key-server`脚本来创建服务器证书(详情请查看 [easy-rsa](https://openvpn.net/easyrsa.html) 文档)。通过设置`nsCertType=server`,指定该证书作为服务器端证书。在客户端配置中添加如下语句: ``` ns-cert-type server ``` 这将阻止客户端连接任何没有在证书中指定`nsCertType=server`的服务器,即使该证书已经通过 OpenVPN 配置文件中的`ca`文件进行了签名。 * 在客户端使用`tls-remote`指令,根据服务器证书的`Common Name`来判断接受或拒绝该服务器连接。 * 使用`tls-verify`脚本或插件,根据服务器证书的嵌入式 X509 附属条目中的自定义测试来判断接受 / 拒绝该服务器连接。 * 使用一个 CA 给服务器证书签名,使用另一个不同的 CA 给客户端证书签名。客户端配置的 ca 指令应该引用为服务器签名的 CA 文件,而服务器配置的 ca 指令应该引用为客户端签名的 CA 文件。
Jonny
April 11, 2023, 7:25 p.m.
778
0 条评论
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
如遇文档失效,可评论告知,便后续更新!
【腾讯云】2核2G云服务器新老同享 99元/年,续费同价
【阿里云】2核2G云服务器新老同享 99元/年,续费同价(不要✓自动续费)
【腾讯云】2核2G云服务器新老同享 99元/年,续费同价
【阿里云】2核2G云服务器新老同享 99元/年,续费同价(不要✓自动续费)
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期