安全测试 如何实现在家访问公司内网服务

欲野 · 2020年09月09日 · 最后由 inkslab 回复于 2020年09月27日 · 377 次阅读

问题来源

最近公司架构调整,将原来在阿里云的开发环境和测试环境迁移到了,公司内网环境,但是,最近在周末的时候,老是有对应的临时需求在周末发布,结果自己在家,没办法访问公司的内网测试环境,很是恼火,根本没办法测试,但无法在在家中解决,自己也不想去公司,需要在内网测试并且上进行分析和定位对应的 bug。第一个想到的就是远程登陆,但公司没有公网 IP,怎么办?

明确需求

经过一波调查明确如解决下需求:
1.一个是可以无视外网 ip 的变化 然后进行网络通信,使自己可以在家访问公司测试环境

经过最终在的调研,最终采用 open*** 实现使用外网访问公司的内网测试环境

知其然知其所以然

open*** 原理

open*是一个基于 OpenSSL 库的应用层实现。其主要技术核心是虚拟网卡和 SSL 协议实现。可以实现多种复杂的业务场景需求,包括单个客户端和服务器,多客户端和服务器 (客户端不通讯),多客户端和服务器 (客户端互通),这里的客户端和服务端都可以扩展到局域网的层面上,其使用工业标准的 SSL/TLS 协议实现第 2 层和第 3 层的安全数据链路*。其优点如下:
1、基于 SSL 协议,安全,并使用单一 TCP 或 UDP 端口即可实现;
2、使用双向验证,服务器只需保存自己的证书和密钥;
3、服务器只接受那些由主 CA 证书签名的客户端,并有撤回机制,而不需要重建整个 PKI;
4、可以实现基于 Common Name 的权限控制。

open*** 网络架构

,英文全称是 Virtual Private Network,字面解释可理解为:虚拟私有网络;可以运行为 Point-to-Point 模式,也可以运行为 Server 模式,在 Server 模式下,服务器可作为网关设备使用,用以给处于外部的不安全网络环境中的 Client 提供安全访问内网服务的通道

以 Server 模式运行的
其走包流程如下图所示:

Open*** 服务搭建与管理

环境准备

硬件
CentOS Linux release 7.7.1908 (Core) 服务器一台
客户端笔记本一台
工具包

https://github.com/Open***/easy-rsa.git

Open*** 搭建

安装依赖包

yum install lz4-devel lzo-devel pam-devel openssl-devel systemd-devel sqlite-devel

从 github 上下载 ope源代码包并解压*

wget https://github.com/Open***/open***/archive/v2.4.7.tar.gz
tar zvxf v2.4.7.tar.gz

编译 open并安装*

cd open***-2.4.7
autoreconf -i -v -f
./configure --prefix=/usr/local/open*** --enable-lzo --enable-lz4 --enable-crypto --enable-server --enable-plugins --enable-port-share --enable-iproute2 --enable-pf --enable-plugin-auth-pam --enable-pam-dlopen --enable-systemd
make && make install

配置系统服务
修改/usr/local/open*/lib/systemd/system/open*-server@.service

 [Service]
...
ExecStart=/usr/local/open***/sbin/open*** --config server.conf

将 open-server@.service 设置成系统服务*

cp /usr/local/open***/lib/systemd/system/open***-server@.service /usr/lib/systemd/system/open***.service 
systemctl enable open***

生成证书

下载 easy-rsa3 并解压

wget https://github.com/Open***/easy-rsa/archive/v3.0.7.tar.gz
tar -xvf v3.0.7.tar.gz

根据 easy-rsa-3.0.7/vars.example 文件生成全局配置文件 vars

set_var EASYRSA_REQ_COUNTRY     "CN" 
set_var EASYRSA_REQ_PROVINCE    "HUBEI"\
set_var EASYRSA_REQ_CITY        "WUHAN"\
set_var EASYRSA_REQ_ORG "ZJ"\
set_var EASYRSA_REQ_EMAIL       "zj@test.com"\
set_var EASYRSA_REQ_OU          "ZJ"\
set_var EASYRSA_KEY_SIZE        2048\
set_var EASYRSA_ALGO            rsa\

生成服务端证书
初始化,生成一系列文件与目录

./easyrsa init-pki   

生成根证书,记住 ca 密码

./easyrsa build-ca    

生成服务端证书

./easyrsa build-server-full server nopass ,nopass参数生成一个无密码的证书

生成 Diffie-Hellman

./easyrsa gen-dh     

生成客户端证书

./easyrsa build-client-full client1 nopass

备注:注:可生成 client1, client2, client3 或对应姓名的客户端证书
为了提高安全性,生成 ta.key

open*** --genkey --secret ta.key

整理证书

cp pki/ca.crt /etc/open***/server/
cp pki/private/server.key /etc/open***/server/
cp pki/issued/server.crt /etc/open***/server/
cp pki/dh.pem /etc/open***/server/
cp ta.key /etc/open***/server/

添加 SQLite 认证

下载 pam_sqlite3 并安装

git clone https://gitee.com/lang13002/pam_sqlite3.git
cd pam_sqlite3
make && make install

添加 pam 认证文件

# vim /etc/pam.d/open***
auth        required    pam_sqlite3.so db=/etc/open***/open***.db table=t_user user=username passwd=password expire=expire crypt=1
account     required    pam_sqlite3.so db=/etc/open***/open***.db table=t_user user=username passwd=password expire=expire crypt=1

创建 sqlite3 数据库文件

sqlite3 /etc/open***/open***.db

sqlite> create table t_user (
     username text not null, 
     password text not null, 
     active int, 
     expire text
);
sqlite> .quit

创建服务端配置文件 (参照 sample/sample-config-files/server.conf 文件)

vim /etc/open***/server/server.conf
port 1194
proto tcp-server
;proto udp
dev tun
topology subnet

ca /etc/open***/server/ca.crt
cert /etc/open***/server/server.crt
key /etc/open***/server/server.key
dh /etc/open***/server/dh.pem

cipher AES-256-CBC
auth SHA512
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA

tls-auth /etc/open***/server/ta.key 0
#tls-crypt /etc/open***/server/ta.key

user nobody
group nobody

server 10.8.0.0 255.255.255.0
;ifconfig-pool-persist ipp.txt
;push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 114.114.114.114"
push "route 192.168.133.0 255.255.255.0"
push "route-gateway 10.200.227.114"

;client-to-client

verify-client-cert none
username-as-common-name
plugin /usr/local/open***/lib/open***/plugins/open***-plugin-auth-pam.so open***

keepalive 10 120
comp-lzo
compress "lz4"
persist-key
persist-tun
status /var/log/open***-status.log
log    /var/log/open***.log
verb 3 

开启路由转发功能与防火墙

# 路由转发
# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1

# 临时启用
# echo 1 > /proc/sys/net/ipv4/ip_forward

# 防火墙
# firewall-cmd --zone=public --add-service=open***

启动 open服务*

systemctl start open***

配置客户端

下载客户端程序

https://gitee.com/lang13002/open***-portable/repository/archive/v1.0?ref=v1.0&sha=1a7401cb8767a8f15726f04613d84458abccd272&format=zip&captcha_type=yunpian&token=335b826daacc4b17a81d2ce8e8f36c8a&authenticate=ced5c39711c343f0bfdb41531204a3ea

安装驱动
运行 open*-portable/tap-windows.exe
设置客户端证书
将上面生成的 ca.crt, client1.crt, client1.key 放到 open
*-portable 的 data/config 下,并修改客户端配置

client
dev tun
proto tcp-client
remote ***server.com 1194

allow-recursive-routing

resolv-retry infinite
nobind
persist-key
persist-tun

remote-cert-tls server
auth-user-pass
auth-nocache
ca ca.crt
cert client1.crt
key client1.key

remote-cert-tls server
auth-user-pass
auth-nocache

cipher AES-256-CBC
auth SHA512
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA

tls-auth ta.key 1

comp-lzo
compress lz4
verb 3
mute 20

备注

注:当有多个客户端时,有多个文件(ca.crt, client1.crt, client1.key, client.o***)需要分发给客户,势必会很麻烦;可以将证书嵌入到客户端配置文件中; 
;ca ca.crt         // 将这行注释掉
;cert client.crt   // 将这行注释掉
;key client.key    // 将这行注释掉
;tls-auth ta.key 1 // 将这行注释掉
<ca>
-----BEGIN CERTIFICATE-----
MIIDGDCCAgCgAwIBAgIJAI9Ld4PlKEiOMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV
....
OCeTQvQ4WhyIvVgURV3ITcAKYFKUQ1sPbpjuZg==
-----END CERTIFICATE---
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIIDODCCAiCgAwIBAgIRAIZoEQ5PvHDs9xpTLMP3RqMwDQYJKoZIhvcNAQELBQAw
......
nCpzC3l8sVezxk2r
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDw1iq3HBe1otCU
......
ullaNc6mu3N/wTPZoQhDOKAO
-----END PRIVATE KEY-----
</key>
<tls-crypt>
#
# 2048 bit Open*** static key
#
-----BEGIN Open*** Static key V1-----
376ff00121bc6cd39fe1382c44be1433
......
-----END Open*** Static key V1-----
</tls-crypt>

连接代理

Open*** 用户管理与日志

安装依赖

pip install peewee tornado

下载 ope-web*

git clone https://gitee.com/lang13002/open***_web.git

创建相应的数据库表

# sqlite3 /etc/open***/ope**n.db
sqlite> .read open***_web/model/open***.sql

添加日志脚本
服务端配置添加运行脚本

script-security 2
client-connect /etc/open***/server/connect.py
client-disconnect /etc/open***/server/disconnect.py

connect.py

!/usr/bin/python

import os
import time
import sqlite3

username = os.environ['common_name']
trusted_ip = os.environ['trusted_ip']
trusted_port = os.environ['trusted_port']
local = os.environ['ifconfig_local']
remote = os.environ['ifconfig_pool_remote_ip']
timeunix= os.environ['time_unix']

logintime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))

conn = sqlite3.connect("/etc/open***/open***.db")
cursor = conn.cursor()
query = "insert into t_logs(username, timeunix, trusted_ip, trusted_port, local, remote, logintime) values('%s','%s', '%s', '%s', '%s', '%s', '%s')" %  (username, timeunix, trusted_ip, trusted_port, local, remote, logintime)
cursor.execute(query)
conn.commit()
conn.close()

disconnect.py

/usr/bin/python

import os
import time
import sqlite3

username = os.environ['common_name']
trusted_ip = os.environ['trusted_ip']
received = os.environ['bytes_received']
sent = os.environ['bytes_sent']

logouttime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))

conn = sqlite3.connect("/etc/open***/open***.db")
cursor = conn.cursor()
query = "update t_logs set logouttime='%s', received='%s', sent= '%s' where username = '%s' and trusted_ip = '%s'" %  (logouttime, received, sent, username, trusted_ip)
cursor.execute(query)
conn.commit()
conn.close()

启动服务

python myapp.py

共收到 13 条回复 时间 点赞

一般都是让网管开个 VPN 就行

内网穿透啥的,和这个有关系吗

married577 回复

内网穿透是另外肥事

公司没有运维😂

您好,我在公司也搭建了 open*,是需要公司防火墙对外开放 open* 端口,客户端在外网才能通过 ip 或域名 + 端口访问到服务端,然后通过服务端转发到公司内网其他机器的

可以无视外网 ip 的变化

remote ***server.com 1194

所以对这里比较疑惑,这域名是哪来的,没看到声明,如何无视外网 ip 变化的?

最简单的方案,内网服务器做 ssh 反射,或者用 frp,都需要公网上找台设备做跳板机。
方便是方便,但安全风险,很多公司不会允许的。

Lie 回复

那个是运行 server 机器的外网 ip 或者域名

昨天有雨 回复

可以无视外网 ip 的变化

那这个是不是假需求了,域名也要 ip 进行解析的
我知道一个付费的工具可以满足这个需求,内网任意机器安装服务端都可,付费,你懂的,所以它怎么穿透内网的我不清楚
主要在这篇帖子里我看了两三遍了,或许我看的不够深、仔细,但是确实没找到答案,希望楼主能解惑一下

Lie 回复

借楼谈一下我对 dnBu 使用场景的理解.如楼主所说 dnBu 的统称为虚拟私有网络,dnBu 会构建一个虚拟的网络将本不能相连的两个网络进行连接.具体是怎么连接的呢?举个例子,比如公司内网有个 192.168.1.111 的 ip 上运行了一个 web 服务,这个 ip 是内网的 ip 我们在外网环境的本地使用 192.168.1.111+web 服务的端口号是没办法访问的.这个时候可以借助 dnBu 来实现外网环境本地访问 192.168.1.111 这台机器上的服务.首先要保证 192.168.1.111 这台机器也是可以访问到外网的然后在外网的某个服务上搭建一台 dnBu server,然后 192.168.1.111 这台机器运行客户端连接 server,我们外网环境的本地也使用客户端连接 server,这个时候在 dnBu 虚拟网络中 192.168.1.111 和 我们的外网环境本地就在同一个网段下了,我们可以通过虚拟网络的 ip+web 服务端口号 的形式去访问对应的 web 服务.

dnBu 可用 base64 解码获取明文

Lie 回复

再来解释下是如何无视外网 ip 变化的:

9# 楼的回复中提到外网环境的本地是通过访问 dnBu 的虚拟网络中 192.168.1.111 的 ip 进行访问的.只要 192.168.1.111 dnBu 的客户端连接不断开,那么 dnBu server 给它分配的虚拟 ip 就不会发生变化.所以不管外网 ip 和连接 dnBu server 后被分配的虚拟 ip 如何变化都不会影响 对 192.168.1.111 这台机器的访问.

昨天有雨 回复

我明白了,原来 client to client 可以这么用,这个确实是可以无视公司外网 ip 变化的
这样的话其实还是需要一台外网 ip 确定的服务器安装 dnBu 服务端
楼主应该是没有用层主的这种方法的呀,dnBu server 没有说清楚,我一直以为还是在内网搭建的,然后利用了内网穿透技术无视外网 ip 变化。。。我从 0 开始研究过,体会比较深的就是这里的,如果网络知识薄弱一点完全无法按照教程来实现的

欲野 #12 · 2020年09月11日 Author
Lie 回复

不好意思,这两天被公司优化了,都在忙着找下家😂
两种模式:
一个是你可以无视外网 ip 的变化 然后进行网络通信。
一个是你这么多机器就一个外网 ip 帮你做端口映射
根据自己的需求去设置对配置文件做对应的修改,在生成对应的 client client 文件,在里我就做了,第一种需求,主要是,利用 client 和 service 建立连接,第二种的话,其实需要讲 open* 的服务器作为跳板机的,然后还有云服务的一些特殊情况下需要借助内网穿透部分的知识,毕竟 open 只是给你做了对应的连接,而不是真正的穿透,这个得根据,自己的实际需求去对应的处理,如果要使用,应用层的话你可以使用 open*+frp 去实现

不是开个 VPN 就搞定了吗?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册