您可以使用 Cloudflare Access 和 Cloudflare Tunnel 构建 Zero Trust 规则,以保护到 MongoDB 部署的连接。Cloudflare Tunnel 需要一个轻量级守护程序 cloudflared 同时运行在部署端和客户端。
在本教程中,运行 cloudflared 的客户端通过 SSH 连接到运行在 Kubernetes 上的 MongoDB 部署。该部署示例旨在将 Compass ↗ 连接到 MongoDB 实例。MongoDB Kubernetes 部署将同时运行 MongoDB 数据库 service 和 cloudflared(作为类似于堡垒机的入站服务)。
本教程涵盖了如何:
- 创建 Cloudflare Access 规则以保护 MongoDB 部署
- 为部署配置 StatefulSet 和服务定义
- 配置到 Cloudflare 边缘的 Cloudflare Tunnel 连接
- 为客户端创建 SSH 配置文件
完成所需时间:
50 分钟
您可以在 Cloudflare Access 中构建一条规则,以控制谁可以连接到您的 MongoDB 部署。Cloudflare Access 规则围绕主机名构建;尽管可以通过 SSH 访问此部署,但在 Cloudflare 中该资源将被表示为主机名。例如,如果您的 Cloudflare 账户中拥有网站 app.com,则可以构建一条规则来保护 mongodb.app.com。
-
在 Cloudflare 仪表板 ↗中,转到 Zero Trust > Access controls(访问控制)> Applications(应用程序)。
-
选择 Create new application(创建新应用程序)。
-
选择 Self-hosted and private(自托管和私有)。
-
选择 **Add public hostname(添加公共主机名)**并输入用户连接到您的部署的子域(例如
mongodb.app.com)。 -
添加 Access 策略以控制谁可以访问该部署。您可以构建一条允许组织中任何人连接的策略,或者您可以基于身份提供商组、多因素方法或国家/地区等信号构建更细粒度的策略。
-
按照其余自托管应用程序创建步骤发布该应用程序。
为了可以通过 SSH 访问,Kubernetes 部署应同时管理 MongoDB 独立服务和 SSH 代理服务。以下配置将部署 1 个数据库服务的副本(在端口 27017 上可用)以及一个 SSH 代理(在端口 22 上可用)。
StatefulSet Configuration
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb-standalone
namespace: mongodb
spec:
serviceName: database
replicas: 1
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
selector: mongodb-standalone
spec:
containers:
- name: mongodb-standalone
image: mongo
command: ["mongod"]
args: ["--config=/config/mongod.conf"]
ports:
- containerPort: 27017
protocol: TCP
name: mongod
volumeMounts:
- name: mongodb-conf
mountPath: /config
readOnly: true
- name: mongodb-data
mountPath: /data/db
- name: tls
mountPath: /etc/tls
- name: mongodb-socket
mountPath: /socket
- name: ssh-proxy
image: ubuntu:20.04
command: ["/scripts/entrypoint.sh"]
ports:
- containerPort: 22
protocol: TCP
name: ssh-port
volumeMounts:
- name: mongodb-socket
mountPath: /socket
- name: scripts
mountPath: /scripts
readOnly: true
- name: ssh-authorized-keys
mountPath: /config/ssh
readOnly: true
resources:
requests:
cpu: 20m
memory: 32Mi
volumes:
- name: mongodb-socket
emptyDir: {}
- name: mongodb-conf
configMap:
name: mongodb-standalone
items:
- key: mongod.conf
path: mongod.conf
- name: tls
secret:
secretName: tls
- name: mongodb-data
persistentVolumeClaim:
claimName: mongodb-standalone
- name: scripts
configMap:
name: scripts
items:
- key: entrypoint.sh
path: entrypoint.sh
mode: 0744
- name: ssh-authorized-keys
configMap:
name: ssh-proxy-config
items:
- key: authorized_keys
path: authorized_keys
mode: 0400相应的服务定义还应指定容器的端口和目标端口(在此情况下为数据库服务和 SSH 代理服务)。
Service Definition
apiVersion: v1
kind: Service
metadata:
name: database
namespace: mongodb
labels:
app: database
spec:
clusterIP: None
selector:
app: database
ports:
- protocol: TCP
port: 27017
targetPort: 27017
---
apiVersion: v1
kind: Service
metadata:
name: ssh-proxy
namespace: mongodb
labels:
app: database
spec:
selector:
app: database
ports:
- protocol: TCP
port: 22
targetPort: 22MongoDB pod 和 SSH 堡垒机将通过空目录卷共享 Unix 套接字(socket)。堡垒机运行的 entrypoint.sh 文件(示例如下)将启动 OpenSSH 服务器。
#!/bin/sh
export TZ=America/Chicago
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
apt-get update -y && apt-get install -y openssh-server
mkdir /root/.ssh
cp /config/ssh/authorized_keys /root/.ssh/authorized_keys
chmod 400 /root/.ssh/authorized_keys
service ssh start
while true;
do sleep 30;
done;接下来,您可以使用 cloudflared 通过 Cloudflare Tunnel 连接到 Cloudflare 的边缘。首先下载并安装 Cloudflare Tunnel 守护程序 cloudflared。
安装完成后,运行以下命令将 cloudflared 实例进行身份验证登录到您的 Cloudflare 账户。
cloudflared login该命令将启动浏览器窗口并提示您登录您的 Cloudflare 账户。选择您已添加到账户中的网站。
在您选择账户中的一个网站后,Cloudflare 将下载一个名为 cert.pem 的证书文件以对该 cloudflared 实例进行身份验证。cert.pem 文件使用证书对您的 cloudflared 实例进行身份验证,并包含您账户的 API 密钥,用以执行诸如 DNS 记录修改等操作。
您现在可以使用 cloudflared 来控制您 Cloudflare 账户中的 Cloudflare Tunnel 连接。
您现在可以创建一个 Tunnel 以将 cloudflared 连接到 Cloudflare 的边缘。您将在下一步中配置该 Tunnel 的详细信息。
运行以下命令以创建一个 Tunnel。您可以将 mongodb 替换为任何您选择的名称。此命令需要 cert.pem 文件。
cloudflared tunnel create mongodb
Cloudflare 将以该名称创建 Tunnel,并为该 Tunnel 生成一个 ID 和凭证文件。
凭证文件与 cert.pem 文件是分开的。与 cert.pem 文件不同,凭证文件包含一个仅对您刚刚创建的命名 Tunnel 进行身份验证的令牌。该文件格式为 JSON,无法对您的 Cloudflare 账户进行更改,也无法创建其他 Tunnel。
如果您已完成 Tunnel 的创建,则可以删除 cert.pem 文件,仅保留凭证文件,并继续在 Cloudflare 仪表板或通过 API 直接管理 DNS 记录。有关这两个文件的不同功能的其他信息,请参阅常用术语列表。
将 JSON 文件存储为 Kubernetes 机密 (secret)。
前面的步骤使用 cloudflared 为您的 Cloudflare 账户生成了凭证文件。当作为服务与 MongoDB Kubernetes 部署一起运行时,您将需要使用 cloudflared 的 Docker 镜像。Cloudflare 在 DockerHub 中提供了一个官方镜像 ↗。
以下配置将运行 cloudflared 的单个副本作为与 MongoDB 和 SSH 代理服务并列的入站点。cloudflared 将把流量代理到 SSH 代理服务。cloudflared 实例将在不同的命名空间中作为其自身的 Deployment 运行,并且如果网络策略允许,将入站到 Kubernetes 节点中的任何服务。
cloudflared Configuration
cloudflared ConfigurationapiVersion: apps/v1
kind: Deployment
metadata:
name: dashboard-tunnel
namespace: argotunnel
labels:
app: dashboard-tunnel
spec:
replicas: 1
selector:
matchLabels:
app: dashboard-tunnel
template:
metadata:
labels:
app: dashboard-tunnel
spec:
containers:
- name: dashboard-tunnel
# Image from https://hub.docker.com/r/cloudflare/cloudflared
image: cloudflare/cloudflared:2020.11.11
command: ["cloudflared", "tunnel"]
args: ["--config", "/etc/tunnel/config.yaml", "run"]
ports:
- containerPort: 5000
livenessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 60
periodSeconds: 60
volumeMounts:
- name: dashboard-tunnel-config
mountPath: /etc/tunnel
- name: tunnel-credentials
mountPath: /etc/credentials
volumes:
- name: dashboard-tunnel-config
configMap:
name: dashboard-tunnel-config
- name: tunnel-credentials
secret:
secretName: tunnel-credentials
---
apiVersion: v1
kind: ConfigMap
metadata:
name: dashboard-tunnel-config
namespace: argotunnel
data:
config.yaml: |
tunnel: 9a00ef26-4997-4de2-83db-631efc74245c
credentials-file: /etc/credentials/k8s-dashboard.json
metrics: :5000
protocol: http2
no-autoupdate: true
ingress:
- hostname: mongodb.widgetcorp.tech
originRequest:
bastionMode: true
- service: http_status:404部署完成后,您可以在客户端运行 cloudflared 以连接到 MongoDB 部署。将以下行添加到您的 SSH 配置文件中,并将示例替换为您的主机名和详细信息。--destination 的值应与先前配置的 SSH 代理服务的 URL 匹配。
Host mongodb
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname mongodb.widgetcorp.tech --destination ssh-proxy.mongodb.svc.cluster.local:22
LocalForward 27000 /socket/mongodb-27017.sock
User root
IdentityFile /Users/username/.ssh/id_rsa这是一次性步骤。当您下次尝试向该部署建立 SSH 连接时,cloudflared 将启动浏览器窗口并提示您进行身份验证。身份验证成功后,如果您拥有有效的会话,便可建立连接。一旦隧道建立,发送到您机器上 localhost:27000 的所有请求都将被转发到 SSH 代理容器上的 /socket/mongodb-27017.sock。
您可以将 MongoDB Compass 设置为连接到 localhost:27000。