0x01 关于openvpn
1 2
| 一种基于OpenSSL加密库的开源VPN实现,此处的主要目的还是旨在说明如何快速安全部署openvpn 关于其内部的加解密细节及封装与解封装过程,相信大家都已经比较熟练了,此处不做过多涉及,暂以实战上手应用为主
|
0x02 openvpn 可工作于两种不同的模式,使用 TUN / TAP 作为接口建立隧道,但需要相应内核支持
1 2 3
| TUN 接口创建的是三层路由隧道,实际中用的较多,TAP 是二层网卡桥接隧道,即创建一个以太网桥接,相对复杂 TAP 接口的好处在于,客户端可以获得 VPN 服务器所处子网的 IP [即,忽略物理上的区别,可以完全将客户端看做是与VPN服务器处于同一子网的另一台机器] 而TUN 接口下所有的客户端则处于一个完全独立的子网内,与 VPN 服务器所在的子网没有关系,待到后面实际部署时,会深有体会的
|
0x03 下面则是 openvpn 提供的两种安全模式
1 2
| Static Key X509 PKI [Public Key Infrastructure]
|
此次演示环境
1 2 3 4
| OpenVpnServer ip: 192.168.3.71 [假设为公网ip] ip: 192.168.6.39 [假设为其所在的内网ip] ip: 192.168.7.39 [假设为其所在的另一个内网ip] OpenVpnClient ip: 192.168.6.41 [内网ip] ip: 192.168.7.41 [另一个内网ip段] 为OpenVpnServer所在内网段的一台linux机器 win7cn ip: 192.168.32.253 [本地机器的内网ip] 作为连接OpenVpnServer的windows访问客户端 CentOS6.8_x86_64 ip: 192.168.32.136 [本地机器的内网ip] 作为连接OpenVpnServer的linux访问客户端
|
我们要实现的最终目的
1 2
| 通过拨入 OpenVpnServer 可在本地直接访问远程内网,即`192.168.32.x`和`192.168.6.x`,本身是两个完全独立相互不同的内网段 但现在要实现的效果就是,可以直接在win7cn或者CentOS6.8上ping通OpenVpnServer所在内网中的OpenVpnClient机器
|
0x04 Ok,明确了最终目的之后,我们就开始来实战部署OpenVpn
首先,进行一些前期的必要环境准备,务必严格保证所有机器时间完全一致,此项非常重要,否则后期OpenVpn客户端在连服务端时会出现证书无法被验证的情况
1 2 3 4
| */2 * * * * /usr/sbin/ntpdate time.nist.gov > /dev/null 2>&1
|
安装C编译器及openssl加密库,众所周知,openvpn依赖openssl对隧道数据进行加密
1
| # yum install -y gcc gcc-c++ openssl openssl-devel
|
禁用selinux,之后一定要记得重启下系统,才可生效
1 2 3
| # setenforce 0 # sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config # shutdown -r now
|
准备好环境所需的源码包,此,分别为数据压缩库和openvpn自身的源码包openvpn的下载地址可能已经被墙掉了,大家暂时挂ss下一下就好了
编译安装LZO,主要用它来压缩通信数据加快传输速度
1 2 3 4
| # tar xf lzo-2.06.tar.gz # cd lzo-2.06 # ./configure && make && make install # echo $?
|
0x05 编译安装OpenVPN,记得要载入lzo一起编译
0x06 安装成功后,我们就开始来实际部署配置OpenVpn
首先,修改默认证书信息,而后,以此来创建各种证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export KEY_COUNTRY="CN" export KEY_PROVINCE="BJ" export KEY_CITY="BeiJing" export KEY_ORG="klionsec" export KEY_EMAIL="klion@rootkit.org" export KEY_EMAIL=klion@rootkit.org export KEY_CN=CN export KEY_NAME=kliosec export KEY_OU=klionsec export PKCS11_MODULE_PATH=changeme export PKCS11_PIN=1234
|
创建服务端证书及密钥 [ 中间会有一处让你输入密码,注意,后续创建证书时的密码最好都跟此密码保持一致,防止认证失败,之后再按照提示输入两次y即可]
1 2
| # ./build-key-server server # ll keys/
|
创建完服务端证书和秘钥后,我们还需要为每一个登陆到OpenVpn服务器的客户端创建一个证书,注意直接用build-key
创建的客户端证书默认是没密码的,也就是说,别人只要拿到你的这套客户端的证书就可以直接连上vpn服务器,有一定风险,当然,前提也得服务端配置中允许同一用户多点登陆才行,后续如果还要新增客户端用户,只需要再用build-key生成即可
1 2
| # ./build-key-pass clientsec 如果你想创建带密码的客户端证书,直接用 build-key-pass 来创建即可 # ll keys/
|
创建秘钥交换协议文件
1 2 3
| # ./build-dh 即迪菲·赫尔曼密钥,会生成dh1024.pem文件,生成过程可能会比较慢,在此期间不要去中断它 # ll keys/ # openvpn --genkey --secret keys/ta.key 生成ta.key文件,防DDos攻击,UDP淹没等恶意攻击,说实话,效果貌似并不太好
|
0x07 创建并修改openvpn服务器配置文件,将需要用到的openvpn证书和密钥复制一份到创建好的keys目录中
1 2 3 4 5 6 7 8 9 10
| # mkdir -pv /etc/openvpn # cd /root/openvpn-2.2.2/easy-rsa/2.0 # cp -ap keys/ /etc/openvpn/ # cd ../../ # cp sample-config-files/{server.conf,client.conf} /etc/openvpn/ # tree /etc/openvpn/ # cd /etc/openvpn/ # cp -a server.conf server.conf.bak # grep '^[^#;]' /etc/openvpn/server.conf > tmp.txt # cat tmp.txt > server.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| # 下面是openvpn服务端的完整配置 # vi server.conf local 192.168.3.71 # 要绑定到的公网ip port 11941 # openvpn服务的默认端口,最好改掉,其实,别人如果全端口扫描还是能扫到 proto tcp # 使用tcp协议,相对稳定 dev tun # 此处使用tun接口 ca /etc/openvpn/keys/ca.crt # ca证书路径 cert /etc/openvpn/keys/server.crt key /etc/openvpn/keys/server.key # openvpn服务端证书路径 dh /etc/openvpn/keys/dh1024.pem server 10.18.0.0 255.255.255.0 # openvpn内网ip地址池 push "route 192.168.6.0 255.255.255.0" # 此项非常重要,即vpn服务器所在的内网段 push "route 192.168.7.0 255.255.255.0" # 如果想让别人拨入成功后能直接跟vpn所在的内网段的机器进行通信,就需要用此方式把配置推到每个客户端 client-to-client # 让openvpn客户端和客户端能相互通信 duplicate-cn # 同一个vpn账号允许同时多点登陆,在上面已经提到过 ifconfig-pool-persist ipp.txt keepalive 10 120 # 发心跳包,每10一次,如果超过120秒都没动静,就自动断开 comp-lzo # 启用传输数据压缩 persist-key persist-tun status openvpn-status.log # 开启OpenVpn服务端日志 log /var/log/openvpn.log # 指定日志存放位置 verb 3 # 指定记录的日志级别
|
0x08 修改完OpenVpn服务端配置后,我们再来稍微调整一些系统配置,如下
开启系统路由转发,因为在拨入成功后还要访问vpn服务器所在内网中的其它机器,所以转发是必须的
1 2
| # sed -i '/net.ipv4.ip_forward/s/0/1/' /etc/sysctl.conf # sysctl -p
|
如果开了iptables,记得把tcp的11941端口[实际中是你自己设置的openvpn服务端口]
和转发都放开,不然客户端可能会连不上,如果压根没开,可暂时不用管
1 2 3 4 5
| # vi /etc/sysconfig/iptables -A INPUT -p tcp --dport 11941 -j ACCEPT # iptables -A INPUT -p tcp --dport 11941 -j ACCEPT # iptables -L -n # /etc/init.d/iptables status
|
最后,我们来尝试启动OpenVpn服务
1 2 3 4 5 6
| # /usr/local/sbin/openvpn --config /etc/openvpn/server.conf & # netstat -tulnp | grep openvpn # echo "/usr/local/sbin/openvpn --config /etc/openvpn/server.conf &" >> /etc/rc.local # tail -n 1 /etc/rc.local # ifconfig -a openvpn服务一旦成功启动系统中就会多出一个名为tun0的虚拟网卡 # pkill openvpn
|
当然,除了手工去加载服务端配置文件来启动,你也可以用openvpn自己提供好的服务启动脚本来配置成常规启动,只是自己不太喜欢这样搞,过程非常简单,如下
1 2 3 4 5 6 7 8
| # cp /root/openvpn-2.2.2/sample-scripts/openvpn.init /etc/init.d/openvpn # chmod 700 /etc/init.d/openvpn # chkconfig openvpn on # chkconfig --list # /etc/init.d/openvpn restart 会有报错 # vi /etc/init.d/openvpn 把148行的*.conf改成server.conf,这个目录下不能有多个.conf否则就会被干扰到 # /etc/init.d/openvpn restart 正常启动 # lsof -i :1194
|
0x09 把服务端完全搞定以后,我们再来看如何在不同系统平台下配置OpenVpn客户端进行连接
先下载并安装好 OpenVpn 的windows版客户端工具,地址已被墙
1
| http://swupdate.openvpn.org/community/releases/openvpn-2.2.2-install.exe
|
此时,再到OpenVpn服务端去把指定客户端的证书及配置文件都下载下来[此处以client用户为例]
,之后再把这些文件全部复制到你OpenVpn客户端的config目录中,此处的OpenVpn客户端config目录是在如下的路径上,而你则要根据你自己的OpenVpn客户端安装目录来调整
1 2
| # cd /etc/openvpn/keys/ # sz ca.crt client.crt client.key
|
1 2
| ca.crt client.crt client.key 所有要复制的文件 C:\Program Files\OpenVPN\config 要复制到的目录
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
client # 声明是客户端 dev tun # 和服务端保持一致,使用tun接口 proto tcp # 同样使用tcp协议,保持一致,不然就没法和服务端进行正常通信了 remote 192.168.3.71 11941 # Openvpn 服务端的ip和端口 resolv-retry infinite nobind persist-key persist-tun ca ca.crt # 客户端证书所在路径 cert client.crt key client.key ns-cert-type server comp-lzo # 压缩传输 verb 3
|
之后,再右键以管理员权限
运行openvpn客户端,点击connect
进行连接即可,如下即表示连接成功,至此,整个OpenVpn的部署工作也就完成了百分之八十,但我们的最终目的是希望能在本地通过拨入vpn直接跟远程内网中的机器进行通信,再次明确目的之后,我们继续
0x10 以上是使用windows客户端来连接OpenVpn服务端,至于如何在linux中使用客户端连接OpenVpn服务端就更简单了,跟OpenVpn服务端一样,先装好OpenVpn,之后只需用openvpn工具加载对应的客户端配置文件即可,注意,是客户端配置文件,另外,此处不需要再配置服务端,单单只是用下openvpn工具而已,具体如下
1 2 3 4 5 6 7 8 9 10 11
| # mkdir /etc/openvpn # cd /etc/openvpn # rz 可以直接把刚刚client的一套证书丢上去 # tree ./ ├── ca.crt ├── client.conf ├── client.crt └── client.key
# 断开以后,第二次重连可能会有些问题,把客户端配置文件改个名就好了 # /usr/local/sbin/openvpn --config /etc/openvpn/client.conf &
|
0x11 再回到我们的最终目的上,如何在本地通过vpn直接跟远程内网进行通信
,方式大概有三种,如下
第一种,把所有要通信的远程内网中的机器的网关都指向OpenVpn服务器的ip,这样,包在回传的时候就能找到本地机器,为了防止重启即失效,可直接把命令放在rc.local
中
1 2
| # route add default gw 192.168.7.39 在OpenVpnClient上添加如下指向 # route -n
|
第二种,走网段路由,在所有要通信的内网的机器上添加如下路由,把来自vpn内网段的数据都直接丢到OpenVpn服务器指定的内网ip上,一样也可以达到目的,但两种方式有个共同的确定,机器比较少的情况下也许还能凑活,如果有几千台机器,每台上都要添加一条这样的指向毕竟是很不现实的
1 2
| # route add -net 10.18.0.0/24 gw 192.168.7.39 在OpenVpnClient上添加如下指向 # route -n
|
所以,我们再来看第三种,利用iptables进行NAT转换,即把源地址为10.18.0.0/24
都转换到指定的内网卡ip上,这样就不用再逐个指定网关了
1 2 3 4
| # /etc/init.d/iptables status 只需在OpenVpnServer服务器上添加如下规则即可 # /sbin/iptables -t nat -A POSTROUTING -s 10.18.0.0/24 -o eth2 -j SNAT --to-source 192.168.7.39 添加规则 # /sbin/iptables -t nat -D POSTROUTING -s 10.18.0.0/24 -o eth2 -j SNAT --to-source 192.168.7.39 删除规则 # /etc/init.d/iptables stop
|
0x12 实际生产环境中,由于各种各样的原因,有时可能还需要禁止指定的客户端用户登陆,方法非常简单,直接注销指定的客户端证书,万一要连续禁用多个vpn账号,那就直接一次性注销多个客户端证书,执行revoke-full后直接覆盖原来的crl.pem文件即可,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # cd /root/openvpn-2.2.2/easy-rsa/2.0 # source vars # vi /root/openvpn-2.2.2/easy-rsa/2.0/openssl-1.0.0.cnf # tail -n 6 /root/openvpn-2.2.2/easy-rsa/2.0/openssl-1.0.0.cnf 先注释如下行 #[ pkcs11_section ] #engine_id = pkcs11 #dynamic_path = /usr/lib/engines/engine_pkcs11.so #MODULE_PATH = $ENV::PKCS11_MODULE_PATH #PIN = $ENV::PKCS11_PIN #init = 0 # ./revoke-full client 指定要注销的客户端用户执行注销 # cat keys/crl.pem # cat keys/index.txt 从该文件中可看到客户端用户的状态,R为已注销 # cp keys/crl.pem /etc/openvpn/keys/ # vi /etc/openvpn/server.conf 再到主配置文件中添加该pem文件位置,然后重启openvpn,该用户登陆即会失效 crl-verify /etc/openvpn/keys/crl.pem # /etc/init.d/openvpn restart
|
下面是vpn账户被禁用后再登陆的效果,你会发现客户端的连接在一直被reset掉
后话:
1 2 3 4
| vpn作为直插目标内部的一个最直接的入口,也颇受入侵者的热爱,尤其是对各种APT团队来讲更是如此,针对此所进行的各种形式的钓鱼也从未休止 其实,关于openvpn自身的漏洞并不多,甚至可以说,几乎没有,有也只是一些第三方库的,另外,基本也不存在什么错误配置能辅助我们渗透的 关于openvpn的内部通信过程,大家可自行拿wireshark&tcpdump仔细好好跟一下基本就看明白了,如果真想深入研究建议直接去阅读2.2的源码 在部署上基本无任何技术含量,只是为了方便大家用,顺便给自己做个备忘,保证后续随时能用即可
|