深色模式
数据加密:静态加密与传输加密落地
摘要:加密要解决两个问题——数据落盘被拿到看不懂(静态加密),数据在网络上被截获看不懂(传输加密)。本文给出 Linux 磁盘层、数据库层、传输层的可复制配置与密钥管理要点。
适用环境
bash
cat /etc/os-release
command -v cryptsetup && cryptsetup --version
lsblk -f | head -10
command -v mysql && mysql --version
openssl version1
2
3
4
5
2
3
4
5
操作步骤
1. 静态加密之磁盘层:LUKS
bash
# 找一块未使用的盘(务必确认设备名,写错会毁数据!)
lsblk
cryptsetup luksFormat --type luks2 /dev/sdb
cryptsetup luksOpen /dev/sdb data_crypt
mkfs.xfs /dev/mapper/data_crypt
mkdir -p /data && mount /dev/mapper/data_crypt /data1
2
3
4
5
6
2
3
4
5
6
luksFormat 会清除目标设备上所有数据
执行前用 lsblk -f 与 blkid 反复确认设备名;新盘建议先确认序列号与容量。
开机自动挂载(用密钥文件而非交互密码):
bash
dd if=/dev/urandom of=/etc/luks-key bs=4096 count=1
chmod 600 /etc/luks-key
cryptsetup luksAddKey /dev/sdb /etc/luks-key
echo "data_crypt /dev/sdb /etc/luks-key luks" >> /etc/crypttab
echo "/dev/mapper/data_crypt /data xfs defaults 0 0" >> /etc/fstab1
2
3
4
5
2
3
4
5
密钥文件放在同一块盘上等于没加密
密钥文件应与加密数据的恢复流程分离管理,理想情况是启动时由密钥中心/TPM 提供。
2. 静态加密之数据库层
MySQL/InnoDB:
ini
[mysqld]
early-plugin-load=keyring_file.so
keyring_file_data=/var/lib/mysql-keyring/keyring
innodb_redo_log_encrypt=ON
innodb_undo_log_encrypt=ON1
2
3
4
5
2
3
4
5
sql
ALTER INSTANCE ROTATE INNODB MASTER KEY;
SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS
FROM information_schema.TABLES WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%';1
2
3
2
3
PostgreSQL 通常用文件系统/磁盘加密;MongoDB 企业版支持 encryptionKeyFile。
3. 静态加密之对象存储与备份
bash
# 备份时用 GPG 加密
tar czf - /data | gpg --symmetric --cipher-algo AES256 \
--batch --passphrase-file /etc/backup.key -o /backup/data-$(date +%F).tar.gz.gpg
# 解密验证
gpg --decrypt --batch --passphrase-file /etc/backup.key \
/backup/data-$(date +%F).tar.gz.gpg | tar tzf - | head1
2
3
4
5
6
2
3
4
5
6
对象存储(S3/OSS)启用服务端加密(SSE-KMS/SSE-S3)并要求强制 HTTPS 访问。
4. 传输加密:内部服务也要 TLS
nginx
server {
listen 443 ssl;
server_name api.internal;
ssl_certificate /etc/ssl/certs/app.internal.crt;
ssl_certificate_key /etc/ssl/private/app.internal.key;
ssl_protocols TLSv1.2 TLSv1.3;
}1
2
3
4
5
6
7
2
3
4
5
6
7
数据库连接开启 TLS:
ini
# MySQL 服务端
[mysqld]
require_secure_transport=ON
ssl_cert=/etc/ssl/certs/mysql.crt
ssl_key=/etc/ssl/private/mysql.key1
2
3
4
5
2
3
4
5
bash
mysql --ssl-mode=REQUIRED -h db.internal -u app -p -e "SHOW STATUS LIKE 'Ssl_cipher';"1
Redis 6+ TLS:
bash
redis-cli --tls --cert /etc/ssl/certs/redis.crt \
--key /etc/ssl/private/redis.key --cacert /etc/ssl/certs/myca.crt ping1
2
2
5. 服务网格 mTLS(K8s 场景)
yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: prod
spec:
mtls:
mode: STRICT1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
bash
kubectl -n prod get peerauthentication
istioctl x describe pod <pod> -n prod | grep -i mtls1
2
2
6. 密钥管理:加密的真正难点
- 密钥与数据分离存放。
- 密钥定期轮换(KMS 支持自动轮换时用自动轮换)。
- 密钥访问有审计(谁在何时解密了什么)。
- 禁止把密钥写进代码仓库或镜像。
bash
# 用 KMS/Transit 做信封加密(Vault 示例)
vault secrets enable transit
vault write -f transit/keys/backup
echo -n "plaintext" | base64 | vault write transit/encrypt/backup plaintext=- | jq -r .data.ciphertext1
2
3
4
2
3
4
7. 确认明文协议清零
bash
ss -lntup | grep -E ':(21|23|80|110|143|389|3306|6379|9200)\s'
tcpdump -i any -A -c 50 'port 3306' 2>/dev/null | grep -i "select\|password" | head -31
2
2
tcpdump 抓到明文 SQL 或口令说明传输加密没做成。
验证
bash
cryptsetup status data_crypt | grep -E 'type|cipher'
lsblk -f | grep crypto_LUKS
mysql --ssl-mode=REQUIRED -h db.internal -u app -p -e "SHOW STATUS LIKE 'Ssl_cipher';"
curl -sI https://api.internal/health | head -1
openssl s_client -connect db.internal:3306 -starttls mysql </dev/null 2>/dev/null | grep -i protocol1
2
3
4
5
2
3
4
5
判定标准:落盘数据在磁盘层或数据库层已加密;内部链路启用 TLS;密钥有独立管理与审计。
常见坑
LUKS 格式化设备选错导致数据全毁
执行前必须 lsblk -f、blkid 双重确认,并在操作前确认备份可用。
加密了磁盘但密钥在同一台机器上
物理接触/镜像拷贝场景下仍可解密。密钥管理(KMS/TPM/密钥中心)才是关键。
只对外网做 HTTPS,内网全明文
内网嗅探与横向移动同样能拿到明文。内部链路也要 TLS,或统一走 mTLS 服务网格。
备份没加密
备份介质(磁带、对象存储)常常权限更松。备份必须独立加密并做恢复演练。
用了 TLS 但没校验对端证书
--ssl-mode=PREFERRED 或不校验 CA 会退化成可中间人。用 REQUIRED+VERIFY_IDENTITY。