<QNAP 453D QTS-5.x> 日志记录:在 Docker 中运行的 Flask 应用安装 自签名 SSL 证书 解决 Chrome 等浏览器证书安全

原因:Chrome 不信任 ssc 证书

使启用了 HTTPS,即使有使用 自签名证书 (self-signed certificate 非由可信的证书颁发机构 【CA,Certificate Authority】签发的)。浏览器 Chrome 默认不信任自签名证书,也会报 **NET::ERR_CERT_AUTHORITY_INVALID**错误。

准备环境:

1. 要用到 opkg

(以前的文章也有写,今天想起来,这个是第三方工具,来自 Entware

2. 要用到 vi 编辑器

a. 升级 apt-get

root@15fcc3463ef3:/app# apt-get update
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Get:4 http://deb.debian.org/debian bookworm/main amd64 Packages [8789 kB]
Get:5 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [2468 B]
Get:6 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [204 kB]
Fetched 9250 kB in 4s (2265 kB/s)                    
Reading package lists... Done
root@15fcc3463ef3:/app#

b. 安装 vi (vim)

root@15fcc3463ef3:/app# apt-get install -y vim
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
...
...
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
Processing triggers for libc-bin (2.36-9+deb12u9) ...
root@15fcc3463ef3:/app# 

解决方法:这里主要介绍 SSC

第一个:浏览器信任自签名证书(自用) 主机名

1. 用于实验的 containter : 31859f34dfc0 15fcc3463ef3

2. Container : 31859f34dfc0 15fcc3463ef3 22e555193e03 6eb329c9609b

功能: <Project-23 Navigator Portal> 文章链接: <Project-23 Navigator Portal> Python flask web 网站导航应用 可编辑界面:添加图片、URL、描述、位置移动-CSDN博客

3. 生成 自签名证书

a. 进入 containter 修改 /etc/ssl/openssl.conf

[~] # docker exec -it 22e555193e03/bin/bash
root@22e555193e03:/app#

b. openss.conf 文件参考:

[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext  # 在我的文件里,添加这一行
x509_extensions    = v3_ext   #在我的文件里,添加这一行

#在我的文件里,添加以下:
[ req_ext ]
subjectAltName = @alt_names

[ v3_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = localhost
DNS.2 = davens
IP.1 = 127.0.0.1

DNS.2 = davens 使用你自己的名字,或者是 FQDN ,也可以多做几个

c. 生成证书

解释命令:

生成自签名证书 openssl req|x509 证书 | newkey rsa:2048 同时创建一个新的证书并生成 2048 位的 RSA 密钥 | -keyout key.pem 私钥的输出文件名 | out cert.der 证书文件名 | days 365 证书的有效期 | nodes 私钥文件不需要设置密码 | config /etc/ssl/openssl.cnf 指定配置参数文件

root@22e555193e03:/app# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -config ./ssl/openssl.cnf
.......+......+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+......+..+....+.....+...+.+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+...+...+............+......+.+...+...+............+........+.........+...+......+....+......+..+...+.......+.......................+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.+.................+.+..+...+.+...............+...+..+......+..........+..+.+.........+......+......+......+.................+.+..............+...+....+.....+...+......+.+......+...+..+...+................+........+......+...................+..+....+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+.+...+........+.............+..+.......+........+...+.......+........+.......+..+.......+......+.....+...+.+........+...+....+.....+......+...+......+....+......+.....+...+......+.+...+.....+.............+..+......+.+......+..+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+............+........+..........+...+........+.+...+...........+.......+..+.+......+.........+..+....+...+.....+.............+..+............+...+..........+..........................+....+..+.+...+..+.......+..+....+..............+......+......+...............+......+....+...+...+........+.+...+......+..+...+.........+.+..+...............+..................+.......+.........+......+.........+...+..+......+...+......+.+............+.....+................+.........+.....+.+...........+................+..+...+............+...+......................+...+.....+.........+..........+......+.....+..........+...+......+.....+...+.+......+.....+.+..+.......+.....+....+.....+..........+..+....+...+..+.........+.+...+.....+...+...+.......+.........+........+............+......+...+....+...+...+..+.......+..+..................+.+..+....+.........+......+...+..+...................+......+........+...+...+......+......+.......+.....+.......+...+..+......+....+.........+.....+....+...+..+.+.....+..........+......+........+...+.........+................+.....+.......+...........+..........+.....+....+...........+.......+..+............+...+..........+..+.........+.......+..+...+.......+..+.........+.+......+..................+............+..+...+......................+...+...+..+...................+...+........+....+...+...+...+.....+...............+.........+......+....+..+.+........+.+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Freedome China!
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:davens
Email Address []:dave@mail.com
root@22e555193e03:/app# 

填写的内容随意, 除了 **Common Name (e.g. server FQDN or YOUR name) []:**davens

c. 证书必须是 PEM 格式

如果使用了 DER, 要转换

root@15fcc3463ef3:/app# openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
root@15fcc3463ef3:/app#

原因:Werkzeug 只能使用 PEM 格式。在 Flask 加载时,使用 der 格式会报错。

细心的你会发现: container ID 已经变了,试错时毁掉了 31859f34dfc0 15fcc3463ef3 22e555193e03 等,这个是新的容器 6eb329c9609b
这个是 container ID 用你自己的来替换 docker ps 可以看到

d. 提前解释一下 CN 与 SAN

这里,理解为 url 要用的名字(主机名,地址全名FQDN):

Tip:

**证书里:SAN**是扩展字段,浏览器会优先验证它。缺少 SAN 是导致浏览器标记自签名证书为 "Not Secure" 的常见问题。您需要确保证书中包含 SAN,并且域名/IP 与实际访问的地址一致。

我花了大都分时间都在不明不白的解决这个问题,直到有文章提到:Chrome 优先验证 SAN,而忽略证书的 **Common Name (CN)**字段。

e. 证书文件:

会在执行 openssl 目录中生成 上面提到的 2个文件:

root@15fcc3463ef3:/app# ls -al
total 48
drwxr-xr-x 1 root root 4096 Nov 17 05:59 .
drwxr-xr-x 1 root root 4096 Nov 17 05:54 ..
-rw-rw-rw- 1 root root 7212 Nov 14 08:05 app.py
-rw-r--r-- 1 root root 1338 Nov 17 05:59 cert.pem
drwxrwxrwx 1 root root 4096 Nov 17 05:54 data
-rw------- 1 root root 1704 Nov 17 05:57 key.pem
-rw-rw-rw- 1 root root   14 Nov 14 09:22 requirements.txt
drwxr-xr-x 1 root root 4096 Nov 17 05:54 static
drwxr-xr-x 2 root root 4096 Nov 17 05:54 templates

4. 挂载到 Flask 容器中

if __name__ == '__main__':
    init_data_file()
    #app.run(host='0.0.0.0', port=9999, debug=True)
    app.run(ssl_context=('cert.pem', 'key.pem'), host='0.0.0.0', port=9999, debug=True)

复制并注释 app.run(host='0.0.0.0', port=9999, debug=True),再修改:

app.run(ssl_context=('cert.pem', 'key.pem'), host='0.0.0.0', port=9999, debug=True)

5. 重启 container

[~] # docker stop 6eb329c9609b
6eb329c9609b
[~] # docker start 6eb329c9609b
6eb329c9609b
[~] # 

6. 再次访问要使用 https

在点开证书信息后,可以看到 Chrome 已经识别到刚才新生成的证书

7. 把证书 cert.pem 下载到 Windows

[/share/Multimedia/2024-MyProgramFiles/23.Navigator_Portal] # docker cp 15fcc3463ef3:/app/cert.pem .
Successfully copied 2.56kB to /share/Multimedia/2024-MyProgramFiles/23.Navigator_Portal/.
[/share/Multimedia/2024-MyProgramFiles/23.Navigator_Portal] # 

8. 向 Windows 导入自签名证书

a. Chrome 导入

浏览器打开这个url: chrome://certificate-manager/localcerts 如下:

b. 使用 certmgr.msc 证书管理器

9. 验证 成功

第二个:certbot 使用 FQDN:davens.myqnapcloud.com

1. 用于实验的 container: 49b23380cba5

2. 这个 container 是我唯一在 Dockerfile 里用了:

# Create non-root user for security
RUN useradd -m appuser && \
    chown -R appuser:appuser /app
USER appuser

默认不是以 root 进入:

[~] # docker exec -it 49b23380cba5 /bin/bash
appuser@49b23380cba5:/app$ 

以 root 进入需要加入 -u root :

[~] # docker exec -u root -it 49b23380cba5 /bin/bash
root@49b23380cba5:/app#

3. 在容器里 安装 certbot

root@49b23380cba5:/app# pip3 install certbot
Collecting certbot
  Downloading certbot-3.0.1-py3-none-any.whl.metadata (8.0 kB)
Collecting acme>=3.0.1 (from certbot)
  Downloading acme-3.0.1-py3-none-any.whl.metadata (1.4 kB)
Collecting ConfigArgParse>=1.5.3 (from certbot)
  Downloading ConfigArgParse-1.7-py3-none-any.whl.metadata (23 kB)
...
...
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

[notice] A new release of pip is available: 24.0 -> 24.3.1
[notice] To update, run: pip install --upgrade pip
root@49b23380cba5:/app# 

3. 获取证书

[~] # docker exec -u root -it 49b23380cba5 /bin/bash
root@49b23380cba5:/app# certbot certonly --standalone -d davens.example.com

因为, 它也是使用 Let's Encrypt 与我的 NAS 发证一家,过程忽略~

后面同第一个方法:

flask加载证书 及以后相同 略

结束语:

还可以使用 Nginx 代理

相关推荐
ccubee23 分钟前
docker 安装 ftp
运维·docker·容器
学习溢出42 分钟前
【网络安全】逆向工程 练习示例
网络·安全·网络安全·渗透测试·逆向工程
黑客Jack44 分钟前
网络安全加密
安全·web安全·php
_微风轻起1 小时前
linux下网络编程socket&select&epoll的底层实现原理
linux·网络
TsengOnce2 小时前
Docker 安装 禅道-21.2版本-外部数据库模式
运维·docker·容器
vortex52 小时前
Burp与其他安全工具联动及代理设置教程
网络·安全
xserver23 小时前
ensp 基于端口安全的财务部网络组建
网络·安全
SimonLiu0094 小时前
[AI]30分钟用cursor开发一个chrome插件
chrome·ai·ai编程
大熊程序猿4 小时前
airflow docker 安装
运维·docker·容器
从后端到QT5 小时前
boost asio 异步服务器
服务器·网络·tcp/ip