OpenVPN + Vagrant应用场景
2019-09-04 10:10:00 Author: xz.aliyun.com(查看原文) 阅读量:221 收藏

  这故事得从公司,渗透组因为临时加的小项目,需要搭个渗透综合类的环境,最初就有了这个方案,朋友问怎么整?跨度有点太大了,只因以前吹牛逼,大学学网络,干运维环境啥都会搭建.....。
  谷歌还能找到很多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   #重新恢复启动

  上述内容虽然看起来部署挺快的,对于没有部署过的人来说还是非常耗时间与精力.....,环境搭建不容易,且搭且珍惜。


文章来源: http://xz.aliyun.com/t/6180
如有侵权请联系:admin#unsafe.sh