如何實現在家訪問公司內網服務

欲野發表於2020-09-09

問題來源

最近公司架構調整,將原來在阿里雲的開發環境和測試環境遷移到了,公司內網環境,但是,最近在週末的時候,老是有對應的臨時需求在週末釋出,結果自己在家,沒辦法訪問公司的內網測試環境,很是惱火,根本沒辦法測試,但無法在在家中解決,自己也不想去公司,需要在內網測試並且上進行分析和定位對應的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

相關文章