这故事得从公司,渗透组因为临时加的小项目,需要搭个渗透综合类的环境,最初就有了这个方案,朋友问怎么整?跨度有点太大了,只因以前吹牛逼,大学学网络,干运维环境啥都会搭建.....。
谷歌还能找到很多OpenVPN的环境部署,国内大多被和谐了。过程中踩了一些坑,分享给圈子,也可以自己搭环境玩一些有意思的东西。
GitHub目前找到最齐全的参考资料:https://github.com/izombielandgit/OpenVPN-HOWTO/blob/master/1.%20HOWTO.md
环境如下:
OpenVPNServer: Ubuntu18 Desktop(公网)假设ip:40.40.40.40 需要装个VirtualBox创建一个虚拟网卡(仅主机模式):ip : 192.168.131.10 gw 192.168.131.1
OpenVPNClient:xxx.xxx.xxx.xxx 注意:不建议在Windows上搭建OpenServer,涉及一些数据包机制转发的会有些麻烦。
为了方便理解这种模式,梳理一副图片,如下所示:
这是部署前梳理流程图,如上图所示,底层是一个Ubuntu or Windows,客户端利用OpenVPN访问公网,Ubuntu内部开启虚拟容器,开启虚拟机而且仅主机模式。用户想要通过客户端OpenVPN连接内网的虚拟机,可以利用Vagrant部署自动化管理容器,Vagrant介绍不太多这里,因为部署很简单,自动化脚本写点Python就好了。
Windows10 OpenVPN部署:
1.下载OpenVpn
2.配置VPNServer网卡适配器
3.Cd Easy-rsa
4.init-config.bat
5.Edit Vars.bat
KEY-COUNTRY = UA
KEY-PROVINCE = Kiev
KEY-CITY = Kiev
KEY- ORG = ServerVPN
6.Cd “c:\Pro OpenVPNPath\easy-rsa”
7.Vars
8.clean-all
9.Build-dh 执行后出现dh4096.pem
10.配置环境变量,OpenVPN
11.Build-ca CreateCA
12.Build-Key-ServerVPN
13.Build-key ClientVPN
14.Openvpn --genkey -- secret keys/ta.key
15.Cp Server.ovpn --> /$path/OpenVPN/config/Server.ovpn
16.Edit Server.ovpn
17.Edit Client
Ubuntu18 OpenVPN部署:
wget -P ~/ https://github.com/OpenVPN/easy-r
mkdir OpenVPNeasy
cd OpenVPNeasy/
wget https://github.com/OpenVPN/easy-rsa
vim easy-rsa // 这个需要修改一些配置,详细参考上述github
tar xvf EasyRSA-unix-v3.0.6.tgz
cd EasyRSA-v3.0.6/
openvpn --genkey --secret ta.key
cp ./ta.key /etc/openvpn/
cp ./pki/ca.crt /etc/openvpn/
cp ./pki/dh.pem /etc/openvpn/
cp /usr/share/doc/openvpn/examples/sample-c
cd /etc/openvpn/
cd server/
gzip -d server.conf.gz 会生成配置文件server.conf
更详细的配置请参考Github,确实写的很好!需要把ca.crt,ta.key,粘贴到客户端,因为必须要验证,这里并没有赋值客户端的密钥或者认证,因为账号密码登陆认证,下面对配置文件重要内容贴上,里面有注释:
OpenVPNServerConfig:
dev-node "vpn-ada" 这里是网卡
mode server
port 12345 绑定端口
proto tcp4-server 使用协议
dev tun
tls-server
tls-auth "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ta.key" 0
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
上述生成的密钥
ca "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\vpn.crt"
key "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\vpn.key"
dh "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\dh2048.pem"
# 可分配多个网段,这是一个大网段,然后可以给指定用户分配固定ip,注意是掩码32Bit的
server 10.10.0.0 255.255.255.0
# 也可以多个server 10.11.0.01 xxxxxxx
# 给客户端配置特殊的ip需求,这个目录自己创建,目录里面的文件就是账户名,比如有一个账户test,那么想给他分配10.10.1.1,就需要在下面创建一个test文件,并且输入ifconfig-push 10.10.1.1 10.10.1.2
client-config-dir ccd
#允许客户端子网互通,这个很重重要,子网内通讯
client-to-client
# 心跳检测
keepalive 10 120
cipher AES-128-CBC
comp-lzo
verify-client-cert require
# 允许密码认证脚本 verify optional ,checkpsw.exe是windwos下OpenVPNServer需要用到的 c写的密码验证程序,高版本OpenVPN要求用脚本可执行的方式认证密钥的正确与错误,正确返回0,错误返回1
# 同样还需要创建密码文件pwd-fle ,格式 test !@#$%asdasd 账户 密码
auth-user-pass-verify checkpsw.exe via-env
script-security 3
# 允许密码认证
username-as-common-name
client-cert-not-required
status openvpn-status.log
log-append openvpn.log
persist-key
persist-tun
verb 3
route-delay 5
route-method exe
# 服务器增加到xxxxx/24的路由
route 10.10.1.0 255.255.255.0
route 10.10.2.0 255.255.255.0
# 让所有客户端都增加xxxxxx的路由
push "route 10.10.0.0 255.255.255.0"
push "route 192.168.131.0 255.255.255.0"
两个平台的检测脚本:checkpwd.exe or checkpwd.sh:
Windows:
#include
#include
#include
#define MAX 1024
int checkpsw(char *username, char *password)
{
FILE *f;
char user[MAX + 2], pass[MAX + 2], active[MAX + 2];
if (!(f = fopen("userpwd", "r")))
{
perror("Open PASSWORD file error");
printf("The password file not found\n");
return -1;
}
while (!feof(f))
{
fscanf(f, "%s %s %s\n", user, pass, active);
if (strcmp(username, user) == 0 && strcmp(password, pass) == 0 && strcmp(active, "1") == 0)
{
fclose(f);
return 0;
//验证通过应该返回0;
}
}
fclose(f);
return 1;
}
int main()
{
int status;
status = checkpsw(getenv("USERNAME"), getenv("PASSWORD"));
return status;
}
Python:
#!/bin/bash
#
# This script will authenticate OpenVPN users against
# a plain text file. The passfile should simply contain
# one row per user with the username first followed by
# one or more space(s) or tab(s) and then the password.
PASSFILE="/etc/openvpn/psw-file"
LOG_FILE="/var/log/openvpn/openvpn-password.log"
TIME_STAMP=`date "+%Y-%m-%d %T"`
###########################################################
if [ ! -r "${PASSFILE}" ]; then
echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." >> ${LOG_FILE}
exit 1
fi
CORRECT_PASSWORD=`awk '!/^;/&&!/^#/&&$1=="'${username}'"{print $2;exit}' ${PASSFILE}`
if [ "${CORRECT_PASSWORD}" = "" ]; then
echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1
fi
if [ "${password}" = "${CORRECT_PASSWORD}" ]; then
echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}
exit 0
fi
echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1
客户端:
client
proto tcp
dev tun
# 连接OpenVPNServer
remote 0.0.0.0 1194
remote-random
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
# cert gttx-client-vpn.crt
# key gttx-client-vpn.key
auth-user-pass
auth-nocache
remote-cert-tls server
tls-auth ta.key 1
route-method exe
#保持服务端和客户端一致
cipher AES-256-CBC
comp-lzo
status openvpn-status.log
部署过程中,开启日志很重要,遇到了毛病就看日志那些报错,找对问题去解决很关键.....不看日志就去百度,很耗费时间
部署成功后,如果客户端用Client,你应该会弹出连接窗口,输入pwd-file账户与密码,如下所示:
Ping试一试咋样:
发现没问题,起码OpenVPN这条线是没问题,这时候你要考虑如何转发呢?Server端如何做,iptables足够了,所以说利用Iptables做ip转发,简单如下:
/etc/sysctl.conf 注释去掉 net.ipv4.ip_forward=1
sysctl -p
Iptables做路由Ip工作相关配置:
# Completed on Fri Aug 9 00:34:00 2019
# Generated by iptables-save v1.6.1 on Fri Aug 9 00:50:54 2019
*nat
:PREROUTING ACCEPT [121:8996]
:INPUT ACCEPT [95:7251]
:OUTPUT ACCEPT [30:2365]
:POSTROUTING ACCEPT [30:2365]
-A POSTROUTING -s 10.10.1.0/24 -j SNAT --to-source 10.66.0.1
-A POSTROUTING -s 10.10.1.0/24 -j SNAT --to-source 192.168.131.0
COMMIT
# Completed on Fri Aug 9 00:50:54 2019
# Generated by iptables-save v1.6.1 on Fri Aug 9 00:50:54 2019
*filter
:INPUT ACCEPT [605:70173]
:FORWARD DROP [24:1456]
:OUTPUT ACCEPT [371:31256]
-A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p tcp -m tcp --dport 12345 -j ACCEPT
-A FORWARD -s 10.10.1.0/24 -d 192.168.131.0/24 -i tun0 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 12345 -j ACCEPT
COMMIT
# Completed on Fri Aug 9 00:50:54 2019
上述很快就布置完成,那就在客户端开ping,192.168.131.xx,发现不通.......,因为一开始Server是Windows,排查错误没有想着客户端排查,折腾许就在服务器端抓包发现OpenVPN根本没有接入.
所以调整思路,客户端抓包,果真路由的问题,因为客户端的网段也在192.168.XX.XX,下一跳的过程无法识别到底走那个网卡,按照本机网卡去跑的,客户端主机网卡去转发路由,并没有走OpenVPN这条路线,其实使用tracert追踪ip路由就可以判定如下:
这明显就有问题,那么发现了问题,看一下OpenVPNCllinet网卡:
客户端局域网Ip如下,所以ping 192.168.131.1的时候,走的是本机这跳网络,没有走OpenVPN,我们需要添加一条路由很明确的告诉他,如何在二层、三层走:
route add 192.168.131.0 mask 255.255.255.0 10.10.1.2
Windows下Vagrant安装:
Vagrant下载:https://www.vagrantup.com/downloads.html
基础功能:
box系列
指令:vagrant box
Usage: vagrant box <subcommand> [<args>]
Available subcommands:
Add vagrant box add [options] <name, url, or path>
list
outdated
prune
remove
Repackage
Update
pull下载各种镜像:https://app.vagrantup.com/boxes/search
在线pull镜像:Vagrant box add https://app.vagrantup.com/generic/boxes/ubuntu1604
vagrant up
增加一个新的BOX之后,需要初始化init
Vagrant init name
查看状态
vagrant status
停止虚拟机
vagrant halt
销毁虚拟机
Vagrant destory [name|id]
Vagrant提供了api,可以远程调用端口,支持curl与Ruby两种格式,可以用Python封装curl实现调用.
★ 插件部署:
vagrant plugin install vagrant-scp
Vagrant global-status
# 拷贝虚拟机
vagrant scp /home/vincent/backend/go-dev/proxy-v default:~
★ 快照管理:
创建快照:
vagrant snapshot save your_snapshot_name
查看快照:
vagrant snapshot list
恢复快照:
vagrant snapshot restore your_snapshot_name
删除快照:
vagrant snapshot delete your_snapshot_name
Vgrant只支持BOX镜像,也就是说Vgrant镜像,封装好的,如何去打包自己的镜像的?
1.管理查看已有的虚拟机:
命令:VboxManage list vms
2.进入到虚拟机目录,然后执行如下操作:
命令:vagrant package --base ”虚拟机名称” --output 输出的os名称
3.打包成功后提示Compressing paCkage ro : //路径
4.vagrant box add zus2019 D:\virtualbox-1\boxtest\zus2019.box 添加打包后.box
收集了一些常用的Vagrant指令,在这也分享一下:
1、vagrant box list #box列表
2、添加box
vagrant box add (box_name) (file_path)
#添加box box_name 为box取的名称 file_path 系统镜像地址
vagrant box add (vagrant_box)
#添加box vagrant box网为vagrant box封装好的box镜像名称。
#vagrant box add laravel/homestead
#vagrant box add laravel/homestead --box-version=0.4.3
#下载指定版本的系统镜像
3、vagrant init (box_name)
#初始化 box_name 本地已安装的box名称
4、vagrant up #启动虚拟机
5、vagrant ssh #ssh登录虚拟机
6、vagrant halt #关掉虚拟机
7、vagrant reload #重启虚拟机
8、vagrant destroy #销毁虚拟机
9、vagrant suspend #虚拟机挂起
10、vagrant status #查看虚拟机运行状态
11、vagrant box remove (boxname) #删除指定的box环境
12、vagrant package #对开发环境进行打包
13、vagrant resume #重新恢复启动
上述内容虽然看起来部署挺快的,对于没有部署过的人来说还是非常耗时间与精力.....,环境搭建不容易,且搭且珍惜。