隔离网络运维技巧-建立自己的工具箱
隔离网络的难处
首先隔离网络是指与互联网隔离的局域网,常见的有党政单位的保密网、政务网、校园网、公司内部网络。
隔离网络有以下几个特点:
- 与互联网一定程度的隔离,比较常见做法是使用网控设备设置 ACL 规则实现
逻辑隔离
,保密级别较高的情况下会断开物理链路实现物理隔离
。 - 无法获取直接获取互联网的公共资源,例如
Yum、apt、python-pypi、dockerhub、maven、npm、rubygems、Windows补丁
等,内部的设备安装或更新软件都很困难。 - 安全防控力度强,需要通过堡垒机、跳板机等才能访问到内部资源,软件、数据进出内部网络都需要经过安全检查;
在运维工作中,自然少不了使用各种工具、各种脚本的
运维人员在日常工作当中,自然少不了使用各种工具、编写各类脚本。能找到现成的 rpm、deb 包还算好的,如果是碰上 Python、Nodejs、Ruby 这类型的脚本程序,装依赖包会让你怀疑人生。
解决方案
最我们可以利用Docker的特性,把我们日常需要的各类 cli 工具打包到 Docker 镜像里面,再拷贝到隔离网络里面,通过 docker run 的方式运行。
事不宜迟,直接上干货。
我们需要准备两台 Linux 机器:
- 一台能连接互联网的 A 机,用作 docker 镜像打包;
- 一台隔离网络内部的 B 机,运维机,用于运行各类工具;
制作运维工具镜像
打包镜像在 A 机上操作,先在上面安装好打包用的 Docker,由于 A 机在互联网环境,安装 Docker 很简单,这里也不赘述了。
基础镜像选用 Alpine Linux
首先它的体积特别小,最简单的环境只需要 5M,把我们需要软件打包进去之后,镜像也是相对小巧的。
其次,Alpine 拥有自己的包管理工具 apk,在线源也是很丰富,可以通过 https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。
网上有很多 alpine、Ubuntu、Debian、CentOS 作为基础镜像的比较,这里就不再赘述
Dockerfile
FROM alpine:3.13.0
LABEL maintainer="LinJiaJian <honos628@foxmail.com>"
# 工作目录设在 /tmp 可以避免产生权限的问题
WORKDIR /tmp
# 替换成国内的清华的 apk 源,提高 Docker Build 的速度
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && \
apk add --no-cache \
# 在这里找需要的软件包,https://pkgs.alpinelinux.org/packages,名字对应加上去就好
bash \
bash-completion \
# vim \
curl \
# openssh-client \
busybox-extras \
redis \
mysql-client \
jq \
bind-tools \
# ca-certificates \
tcptraceroute \
mtr \
iproute2 \
# postgresql-client \
ansible \
tzdata && \
# 调整成上海时区,避免一些时区的问题
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
apk del tzdata
# alpine没有 tcping 现成的软件包,需要使用 tcptraceroute + 脚本的形式来使用,所以要这样装
RUN curl -s 'http://www.vdberg.org/~richard/tcpping' -o /bin/tcpping && \
chmod 755 /bin/tcpping && \
ln -s /bin/tcpping /bin/tcping
# ENTRYPOINT设置成这样,在docker run的时候比较方便
ENTRYPOINT ["/bin/bash", "-c"]
构建脚本
打包构建的脚本 build.sh 放在 Dockerfile 同级目录
#!/usr/bin/env bash
# --------------------
# File: build.sh
# Project: ops_tools
# Purpose: 打包构建 ops tools,每次都刷新latest
# Author: Jan Lam (honos628@foxmail.com)
# Last Modified: 2021-01-30 14:24:37
# --------------------
VERSION="1.2.0"
docker build --no-cache \
-t honos628/ops_tools:${VERSION} \
-t honos628/ops_tools:latest \
.
# 清理 <none> 的 docker image
docker images |grep none |awk '{print $3}' |xargs docker rmi
# 打包压缩
rm -f *.tar *.xz
docker save -o honos628__ops_tools.tar honos628/ops_tools:latest
xz honos628__ops_tools.tar
打包
$ sudo bash build.sh
Sending build context to Docker daemon 48.78MB
Step 1/6 : FROM alpine:3.13.0
---> 7731472c3f2a
Step 2/6 : LABEL maintainer="LinJiaJian <honos628@foxmail.com>"
---> Running in 3f76499dfb25
...
Successfully built b2f36a6850c3
Successfully tagged honos628/ops_tools:1.2.0
Successfully tagged honos628/ops_tools:latest
Deleted: sha256:34015687c8512959067cfa75bdf1b7263eda2ef9a811344c0ece998143e844eb
Deleted: sha256:560634b288c41c9204ef9b6d11832873896a4ecbac86402fa8251ffb8c3bd04d
Deleted: sha256:3a11d94fdc0c29dc166b108e80af4ef5c1256b22bc66eb3bbefcb4e4ccb7f89c
...
# 看到 Successfully 基本就没啥问题了。
# 再看看docker镜像
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
honos628/ops_tools 1.2.0 b2f36a6850c3 4 minutes ago 381MB
honos628/ops_tools latest b2f36a6850c3 4 minutes ago 381MB
alpine 3.13.0 7731472c3f2a 2 weeks ago 5.61MB
# 其实因为我装了 ansible,后面有一大堆 python 的依赖,镜像才会这么大。
# 装装一些编译好的工具,镜像估计只有50M左右。
$ sudo ls -ltrsh
total 47M
4.0K -rw-rw-r-- 1 jan jan 1.1K Jan 30 14:32 Dockerfile
4.0K -rwxrwxr-x 1 jan jan 578 Jan 30 14:32 build.sh
47M -rw------- 1 jan jan 47M Jan 30 14:34 honos628__ops_tools.tar.xz
# 压缩之后只有47M
honos628_ops_tools.tar.xz 就是我们工具箱镜像了。
配置隔离网络运维机
隔离网络的运维机(B 机),也需要安装 docker 运行环境。这里以 CentOS 7.5 以及最新版本的 Docker 20.10.1 举例。
没有 YUM 源,所以我们将相关 rpm 包都下载好,大概 100M 左右。
$ sudo ls -ltrsh
total 103M
9.1M -rw-r--r-- 1 root root 9.1M Jan 5 10:53 docker-ce-rootless-extras-20.10.1-3.el7.x86_64.rpm
34M -rw-r--r-- 1 root root 34M Jan 5 10:53 docker-ce-cli-20.10.1-3.el7.x86_64.rpm
27M -rw-r--r-- 1 root root 27M Jan 5 10:53 docker-ce-20.10.1-3.el7.x86_64.rpm
34M -rw-r--r-- 1 root root 34M Jan 5 10:53 containerd.io-1.4.3-3.1.el7.x86_64.rpm
56K -rw-r--r-- 1 root root 55K Jan 5 11:12 fuse-overlayfs-0.7.2-6.el7_8.x86_64.rpm
84K -rw-r--r-- 1 root root 82K Jan 5 11:12 slirp4netns-0.4.3-4.el7_8.x86_64.rpm
60K -rw-r--r-- 1 root root 57K Jan 5 11:12 libseccomp-2.3.1-4.el7.x86_64.rpm
40K -rw-r--r-- 1 root root 40K Jan 5 11:12 container-selinux-2.119.2-1.911c772.el7_8.noarch.rpm
84K -rw-r--r-- 1 root root 82K Jan 5 11:16 fuse3-libs-3.6.1-4.el7.x86_64.rpm
# 全部装上去就好了。
$ sudo rpm -Uvh *.rpm
$ sudo systemctl start docker
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker ps有正常返回就好
把刚才我们打包好的honos628__ops_tools.tar.xz
也放上去,解压并导入 docker
# 解压
$ sudo xz -d honos628__ops_tools.tar.xz
# 导入
$ sudo docker load -i honos628__ops_tools.tar
Loaded image: honos628/ops_tools:latest
# 查看下镜像
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
honos628/ops_tools latest b2f36a6850c3 4 minutes ago 381MB
工具使用方法
工具导入完成之后,直接运行 docker run 就可以达到效果了
$ docker run --rm honos628/ops_tools "mysql --version"
mysql Ver 15.1 Distrib 10.5.8-MariaDB, for Linux (x86_64) using readline 5.1
$ docker run --rm honos628/ops_tools "redis-cli --version"
redis-cli 6.0.10 (git:63eb61be-dirty)
$ docker run --rm honos628/ops_tools "curl -sI www.baidu.com"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Sat, 30 Jan 2021 18:35:14 GMT
Etag: "575e1f6f-115"
Last-Modified: Mon, 13 Jun 2016 02:50:23 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
但是!运行起来实在太麻烦了。敲一大坨命令,一点也不优雅。我们可以利用 shell 脚本再改造一下。
例子 1 redis-cli
我们以 redis-cli 为例,做一个脚本
redis-cli.sh
#!/usr/bin/env bash
# --------------------
# File: redis-cli.sh
# Project: ops_tools
# Purpose: 模拟redis-cli
# Author: Jan Lam (honos628@foxmail.com)
# Last Modified: 2021-01-31 02:44:59
# --------------------
#!/bin/env bash
ARGS="$*"
#echo $ARGS
docker run --rm -it --network host \
honos628/ops_tools \
"redis-cli ${ARGS}"
拷贝到 PATH,软连接、赋予执行权限
$ cp ./redis-cli.sh /usr/local/sbin/redis-cli.sh
$ cd /usr/local/sbin/
$ chmod +x redis-cli.sh
$ ln -s redis-cli.sh redis-cli
# OK,我们运行一下试试
$ redis-cli -h 192.168.33.33 -p 3480 -a secret_password info
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Server
redis_version:4.1.1
redis_git_sha1:afb9ef6e
redis_git_dirty:0
redis_build_id:764b9ad3431f8368
redis_mode:cluster
os:Linux 3.10.0-957.27.2.el7.x86_64 x86_64
.....
# Cluster
cluster_enabled:1
# Keyspace
db0:keys=15497,expires=13870,avg_ttl=1069050
例子 2 ansible
ansible 更为复杂点,涉及 ansible.cfg、hosts 文件、playbook 的剧本文件。所以我们要把目录挂载到容器里面。
# ansible 目录我设置在了/opt/ansible_home,随便写了一些配置,下面是目录结构
/opt/ansible_home/
├── ansible.cfg
├── hosts
├── roles
│ ├── nginx_lb
│ │ ├── files
│ │ └── tasks
│ │ └── main.yml
│ └── users
│ ├── files
│ └── tasks
│ └── main.yml
└── setup.yml
ansible.sh
#!/usr/bin/env bash
# --------------------
# File: ansible.sh
# Project: ops_tools
# Purpose: 模拟ansible脚本
# Author: Jan Lam (honos628@foxmail.com)
# Last Modified: 2021-01-31 02:43:57
# --------------------
#!/bin/env bash
ARGS="$*"
#echo $ARGS
WORKDIR="/mnt"
ANSIBLE_HOME="/opt/ansible_home"
[[ ! -d "${ANSIBLE_HOME}" ]] && mkdir -p ${ANSIBLE_HOME}
echo "Ansible Home is: ${ANSIBLE_HOME}"
cd ${ANSIBLE_HOME}
#ls -ltrsh
echo "----"
docker run --rm -it --network host \
-w ${WORKDIR} \
-v ${ANSIBLE_HOME}:${WORKDIR} \
honos628/ops_tools \
"ansible ${ARGS}"
拷贝到 PATH,软连接、赋予执行权限
$ cp ./ansible.sh /usr/local/sbin/ansible.sh
$ cd /usr/local/sbin/
$ chmod +x ansible.sh
$ ln -s ansible.sh ansible
# 试运行
$ ansible all -mping
Ansible Home is: /opt/ansible_home
----
192.168.34.194 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.34.217 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.34.200 | SUCCESS => {
"changed": false,
"ping": "pong"
}
## 需要注意,因为脚本引号的问题,所以参数带引号的要转义一下
$ ansible all -mshell -a \"ls -ltrsh\"
Ansible Home is: /opt/ansible_home
----
192.168.34.217 | CHANGED | rc=0 >>
total 0
192.168.34.194 | CHANGED | rc=0 >>
total 0
192.168.34.200 | CHANGED | rc=0 >>
total 0
其他命令也类似这样用脚本处理一下就好了。
无论是运行速度,还是运行的手感、反馈结果,都与真实的命令没太大区别。
完美 >_<