tinc 内网集群架构

常用于中小企业内部网络开发, 如外网服务器负责网络转发到内部公司网络服务器, 将数据功能转发到内网服务器当中,
将数据在广域网缩小成局域网处理.

这里采用 tinc 来搭建内网局域网, 首先这里假设外网服务器 111.111.111.111 来做外网路由, 也就是外网服务器.

注意这里最好对外公网暴露好端口号作为路由接入端口, 建议加入以 7000 做网段, 预留好端口 7000 来做其他内网服务器接入口,
7001-7999 则是需要暴露转发的服务.

同时这里注意开启内核转发:

1
2
3
4
5
6
7
8
9
10
11
# 查看 ip_forward 转发是否开启
sysctl -a|grep ip_forward

# 首次开启
sudo echo 1 > /proc/sys/net/ipv4/ip_forward

# 启用 tun 设备
sudo modprobe tun

# 确认是否启用成功
ls /dev/net/tun

这里 Ubuntu 环境来做发行版环境, 首先可以安装 tinc :

1
sudo apt install tinc # 安装 tinc, 主网服务器和子网服务器都要

这里可以查看 tinc 在系统服务配置( /lib/systemd/system/tinc@.service ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

[Unit]
Description=Tinc net %i
Documentation=info:tinc
Documentation=man:tinc(8) man:tinc.conf(5)
Documentation=http://tinc-vpn.org/docs/
PartOf=tinc.service
ReloadPropagatedFrom=tinc.service

[Service]
Type=simple
WorkingDirectory=/etc/tinc/%i
EnvironmentFile=/etc/default/tinc
ExecStart=/usr/sbin/tincd -n %i -D $EXTRA
ExecReload=/usr/sbin/tincd -n %i -kHUP
KillMode=mixed
Restart=on-failure
RestartSec=5
TimeoutStopSec=5

[Install]
WantedBy=tinc.service

这里可以看到 WorkingDirectory=/etc/tinc 配置的路径, 所以需要基于这个目录来配置.

还有需要注意很多云服务器商的 ufw 防火墙默认开启, 所以需要记得放行端口:

1
2
3
sudo ufw allow 7000/tcp
sudo ufw allow 7000/udp
sudo ufw reload

配置外网

这里假设虚拟内网名为 vps, 以此创建配置服务:

1
2
3
4
5
6
7
8
/etc/tinc
└── vps
├── hosts
│ └── vps
├── rsa_key.priv
├── tinc.conf
├── tinc-down
└── tinc-up

文件配置:

  • tinc.conf 为 tincnet 的配置文件,
  • tinc-up 为启动该网络时自动执行的脚本
  • tinc-down 为关闭该网络时自动执行的脚本
  • hosts 文件夹保存着各个节点(路由器)的信息。

按这种方式来做配置:

1
2
3
4
5
6
# 创建配置目录
sudo mkdir /etc/tinc/vps
sudo mkdir /etc/tinc/vps/hosts

# 编写配置文件
sudo vim /etc/tinc/vps/tinc.conf

/etc/tinc/vps/tinc.conf 配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 通用配置
Name = vps
Interface = tinc
Autoconnect = yes

# 虚拟网模式
# router / switch / hub ,相对应路由、交换机、集线器
# 默认模式 router
Mode = router

# 压缩数据等级,0 (关闭),1 (fast zlib) 至 9 (best zlib),10 (fast lzo) 和 11 (best lzo)
# 压缩等级越高, 所需要的 CPU 占用性能越大
Compression=9

# 数据加密方式
# 加密方式可选: aes-128-cbc aes-256-cbc
Cipher = aes-256-cbc

# 数据加密强度
# 加密强度可选: sha256 sha128 sha1
Digest = sha256

# 内网挂载配置
Device = /dev/net/tun

# 挂载私钥文件
PrivateKeyFile=/etc/tinc/vps/rsa_key.priv

/etc/tinc/vps/tinc-up 路由挂载脚本:

1
2
3
4
5
#!/bin/sh

# 10.7.0.0/24 作为网域, 用 10.7.0.x 是为了配合 7000 端口映射, 具体可以自定义
# 内部虚拟网对外公网主机设置 10.7.0.1, 这就是内网虚拟机的地址
ifconfig $INTERFACE 10.7.0.1 netmask 255.0.0.0

/etc/tinc/vps/tinc-down 路由关闭脚本:

1
2
3
4
#!/bin/sh

# 关闭虚拟内网
ifconfig $INTERFACE down

这两个脚本需要赋予启动权限:

1
sudo chmod +x /etc/tinc/vps/tinc-*

编写虚拟内网节点信息:

1
sudo vim /etc/tinc/vps/hosts/vps # 编写虚拟网主节点配置

主节点配置 /etc/tinc/vps/hosts/vps :

1
2
3
4
5
6
7
8
# 主节点公网IP地址, 也就是对外暴露的公网地址
Address = 111.111.111.111

# 主节点公网端口号, 对外的暴露端口
Port = 7000

# 主节点内网地址, 10.7.0.1 这就是配置的虚拟网地址
Subnet = 10.7.0.1/32

之后就是生成密钥在虚拟网:

1
2
# 生成密钥强度 4096 的私有密钥, 默认两个回车保存配置
sudo tincd -n vps -K4096

至此服务器配置已经完成, 这时候就是挂载服务器查看:

1
2
3
4
5
6
7
8
9
10
11
12
# 设置服务启动和开机启动
sudo systemctl start tinc.service
sudo systemctl enable tinc.service
sudo systemctl start tinc@vps.service
sudo systemctl enable tinc@vps.service

# 查看服务器是否挂载, 如果有看到挂起 `tinc` 网卡这就是配置完成
sudo ifconfig

# 可以考虑重启下看看是否开机会不会自动部署虚拟内网
# 查看监听端口是否挂起
sudo lsof -i :7000

之后就是客户端配置, 用于给公司/家庭内网组子网.

配置子网

公司/家庭内网只需要配好内网服务器, 之后就是按照之前流程配置再走一遍子网配置.

首先还是配置出新的配置:

1
2
3
4
5
6
7
8
9
/etc/tinc
└── vps
├── hosts
│ ├── vps
│ └── slave_1
├── rsa_key.priv
├── tinc.conf
├── tinc-down
└── tinc-up

新的子网名称为 slave_1 , 这里按照之前流程走遍:

1
2
3
4
5
6
# 创建配置目录
sudo mkdir /etc/tinc/vps
sudo mkdir /etc/tinc/vps/hosts

# 编写配置文件
sudo vim /etc/tinc/vps/tinc.conf

这里注意 /etc/tinc/vps/tinc.conf 是有所变化的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 通用配置, 注意 Name 是唯一的, 也就是子网必须修改成其他
# 也就是修改成 slave_1 表示 子网01, 后期扩展其他内网可以推到 slave_2...
Name = slave_1

# 注意,这里需要设置加入主网
ConnectTo = vps

Interface = tinc
Autoconnect = yes

# 虚拟网模式
# router / switch / hub ,相对应路由、交换机、集线器
# 默认模式 router
Mode = router

# 压缩数据等级,0 (关闭),1 (fast zlib) 至 9 (best zlib),10 (fast lzo) 和 11 (best lzo)
# 压缩等级越高, 所需要的 CPU 占用性能越大
Compression=9

# 数据加密方式
# 加密方式可选: aes-128-cbc aes-256-cbc
Cipher = aes-256-cbc

# 数据加密强度
# 加密强度可选: sha256 sha128 sha1
Digest = sha256

# 内网挂载配置
Device = /dev/net/tun

# 挂载私钥文件
PrivateKeyFile=/etc/tinc/vps/rsa_key.priv

/etc/tinc/vps/tinc-up 路由挂载脚本:

1
2
3
4
#!/bin/sh

# 注意, 这里配置的虚拟网必须是唯一, 也就是虚拟网地址
ifconfig $INTERFACE 10.7.0.2 netmask 255.0.0.0

/etc/tinc/vps/tinc-down 路由关闭脚本, 这个没有什么变化:

1
2
3
4
#!/bin/sh

# 关闭虚拟内网
ifconfig $INTERFACE down

最后赋予启动权限:

1
sudo chmod +x /etc/tinc/vps/tinc-*

主节点配置 /etc/tinc/vps/hosts/slave_1, 这就是子网的配置文件:

1
2
3
4
5
6
7
8
# 主节点公网IP地址, 也就是对外暴露的公网地址
Address = 111.111.111.111

# 主节点公网端口号, 对外的暴露端口
Port = 7000

# 子节点内网地址, 10.7.0.2 这就是配置的虚拟网地址
Subnet = 10.7.0.2/32

子网也需要生成密钥在虚拟网:

1
sudo tincd -n vps -K4096

注意

这里需要注意, 访问的时候是只认准 /etc/tinc/vps/hosts 内部交换的配置密钥文件, 所以主网/子网这个目录都需要进行同步.

也就是对外公网和内网的 hosts 目录内部文件要一致, 也就是 slave_1vps 同步一起, 这是十分关键的步骤.

也就是双方 hosts 需要交换:

1
2
3
4
5
# 在主网内部追加子网配置
sudo vim /etc/tinc/vps/hosts/slave_1 # 拷贝 slave_1 内容过去

# 在子网内部追加主网配置
sudo vim /etc/tinc/vps/hosts/vps # 拷贝 vps 内容过去

最后主网/子网重启下就行了:

1
2
3
4
5
# 记得主网必须要先重启, 之后设置子网服务启动和开机启动
sudo systemctl start tinc.service
sudo systemctl enable tinc.service
sudo systemctl start tinc@vps.service
sudo systemctl enable tinc@vps.service

测试访问

可以测试在内网服务跑 Nginx 的服务挂起个 7002 服务, 挂载服务( /etc/nginx/conf.d/echo.conf):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server{
# 监听内网服务的端口
listen 10.7.0.2:7002;

location / {
# 设置默认的返回格式
default_type text/html;

# 这里返回 http 为了兼容中文最好添加头信息
add_header Content-Type 'text/html; charset=utf-8';

# 设置返回的内容和状态码( 200 )
return 200 'Access Passed';
}
}

Nginx 之后就可以在 10.7.0.1 主网测试访问地址:

1
2
# 测试公网内部访问子网的服务,如果能够显示 'Access Passed' 就代表内网已经连接
curl 10.7.0.2:7002

批量端口转发

这里已经对外暴露 7000 端口作为主网监听, 之后主网 7001-7999 就需要把转发到子网的 7001-7999, 这里采用 Nginx
做直接代理转发.

注意云服务内部放行 7001-7999 端口TCP服务, 建议预留好映射 7022 作为主网转发到 ssh 的地址

Nginx 默认不支持范围端口转发, 所以采用脚本来处理生成配置让 Nginx 加载:

1
2
3
4
5
6
7
8
# 所有的操作基于 /etc/nginx 目录处理
cd /etc/nginx

# 创建转发目录
sudo mkdir -p /etc/nginx/stream/7000

# 追加配置目录
sudo vim /etc/nginx/nginx.conf

修改主目录加入 stream 流量转发:

1
2
3
4
5
6
7
8
9
10
11
12
13
events {
worker_connections 1024;
# multi_accept on;
}

# 流转发配置
stream {
# 加载 7000 服务组服务
include /etc/nginx/stream/7000/*.conf;

# 后续其他服务组再次追加
include /etc/nginx/stream/8000/*.conf;
}

编写脚本处理那些编写流程, 方便来做处理:

1
sudo vim /etc/nginx/stream-group.sh

编写 /etc/nginx/stream-group.sh 脚本内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/bash

# root? sudo?
if [ "$UID" -ne 0 ]; then
echo "Script is running as normal user[require: sudo]"
fi

cd $(dirname $0)
ROOT_PATH=$(pwd)
STREAM_PATH="${ROOT_PATH}/stream"
STREAM_FILE="access.conf"
STREAM_HOSTNAME="10.7.0.2"


# directory exists
if [ ! -d $STREAM_PATH ]; then
mkdir $STREAM_PATH
fi


# input group number
while :
do
read -p "Input Stream Group Number[2-64]:" group
if [[ "$group" -gt 1 && "$group" -lt 65 ]]; then
break
else
echo "$group is not between 2 and 64"
fi
done

# backup directory
STREAM_GROUP=$(( $group * 1000))
STREAM_GROUP_PATH="$STREAM_PATH/$STREAM_GROUP"

# directory exists? backup
if [ -d $STREAM_GROUP_PATH ]; then
while :
do
read -p "Backup ${STREAM_GROUP_PATH}[y/n]:" is_bak
if [ "$is_bak" = "y" ]; then
BAK_FILE=${STREAM_GROUP_PATH}_$(date +%Y%m%d)
BAK_FILE="${BAK_FILE}.tar"
tar -cvf $BAK_FILE $STREAM_GROUP_PATH
echo "Backup File: ${BAK_FILE}"
mv -f ${STREAM_GROUP_PATH} /tmp/$STREAM_GROUP
mkdir $STREAM_GROUP_PATH
break
elif [ "$is_bak" = "n" ]; then
rm -rf /tmp/$STREAM_GROUP
mv -f ${STREAM_GROUP_PATH} /tmp/$STREAM_GROUP
mkdir $STREAM_GROUP_PATH
break
fi
done
else
mkdir $STREAM_GROUP_PATH
fi

# write nginx config
STREAM_GROUP_FILE="${STREAM_GROUP_PATH}/${STREAM_FILE}"
touch $STREAM_GROUP_FILE


# each port
STREAM_GROUP_INDEX=$(( $STREAM_GROUP + 1))
STREAM_GROUP_END=$(( $STREAM_GROUP + 999))
while [ $STREAM_GROUP_INDEX -le $STREAM_GROUP_END ]; do
#echo $STREAM_GROUP_INDEX

# write server
echo "# ${STREAM_GROUP_INDEX} BEGIN =====================" >> $STREAM_GROUP_FILE
echo "server {" >> $STREAM_GROUP_FILE
echo " listen ${STREAM_GROUP_INDEX} reuseport;" >> $STREAM_GROUP_FILE
echo " tcp_nodelay on;" >> $STREAM_GROUP_FILE
echo " proxy_pass ${STREAM_HOSTNAME}:${STREAM_GROUP_INDEX};" >> $STREAM_GROUP_FILE
echo "}" >> $STREAM_GROUP_FILE
echo "# ${STREAM_GROUP_INDEX} END =====================" >> $STREAM_GROUP_FILE
echo "" >> $STREAM_GROUP_FILE
echo "" >> $STREAM_GROUP_FILE


STREAM_GROUP_INDEX=$((STREAM_GROUP_INDEX+1))
done

这里设置可执行之后生成配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
sudo chmod +x /etc/nginx/stream-group.sh # 赋予权限
sudo /etc/nginx/stream-group.sh # 执行生成分组, 输入 7 生成 7001-7999的分组数据

# 可以看到 access.conf 配置文件内容
sudo vim /etc/nginx/stream/7000/access.conf

# 没问题重新加载 nginx 即可
sudo systemctl restart nginx.service

# 外网访问私有网络端口, 之前说过访问 111.111.111.111 是外网, 内网服务器开放 7002 端口
# 现在直接可以看下是否转发成功
curl 111.111.111.111:7002

至此就能生成公网代理转发到内网的服务.