Rootop 服务器运维与web架构

2025-06-19
发表者 Venus
mTLS双向认证已关闭评论

mTLS双向认证

mTLS 通信流程
1 证书准备:
服务端和客户端都拥有各自的 X.509 证书和私钥
证书由同一个受信任的 CA 签发(可以是私有 CA)

2 握手过程(TLS Handshake):
客户端发起连接请求
服务端返回其证书
客户端验证服务端证书(CA 签名 + 域名匹配)
客户端也发送自己的证书
服务端验证客户端证书
双方协商会话密钥 R,建立加密通道

3 通信加密:
所有数据通过协商出的密钥进行加密传输(R为对称加密秘钥,不再使用公钥加密)
双方身份已验证,通信安全可信

公钥加密是为“身份验证 + 密钥协商”服务的,不是为了日常数据传输。真正保护数据的是协商出来的对称密钥 R。

nginx实现方式:

server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate     /etc/nginx/certs/server.crt;
    ssl_certificate_key /etc/nginx/certs/server.key;

    ssl_client_certificate /etc/nginx/certs/ca.crt;
    ssl_verify_client on;  # 强制客户端提供证书

    location / {
        proxy_pass http://backend;
    }
}

参考:https://help.aliyun.com/zh/api-gateway/traditional-api-gateway/user-guide/mutual-tls-authentication

2025-06-19
发表者 Venus
作为CA (Certificate Authority)机构颁发证书已关闭评论

作为CA (Certificate Authority)机构颁发证书

# 1、生成私钥公钥,自己作为ca。
mkdir ca && cd ca
openssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 3650
用自己的私钥给自己签名,颁发者和持有者一样。有效期10年。
有了私钥和证书就可以给其它证书签名请求进行证书签发。


# 给服务器(域名)颁发证书
# 自己生成私钥和csr,可以自己生成也可以客户端生成
mkdir entain && cd entain
openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -key server.key -out server.csr

# 创建一个SAN文件
[root@docker-server entain]# cat san.conf 
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = x.com
DNS.2 = entain.x.com
IP.1 = 127.0.0.1


# 用ca的证书给csr颁发证书
openssl x509 -req -in server.csr -CA ../ca/ca.crt -CAkey ../ca/ca.key  -CAcreateserial -out server.crt -days 365 -extfile san.conf


# 验证证书链
检查 server.crt 是否正确签署:
openssl verify -CAfile ../ca/ca.crt server.crt
如果输出 server.crt: OK,说明证书链正确。

windows必须导入 ca.crt 作为受信任的根证书,否则浏览器或系统不会信任服务器证书。



########################################################################################################################################
# 其它补充资料
# 私钥、公钥、证书 三者的关系
为什么 .crt(证书) 不是公钥?
.crt 是完整的证书,里面包含:
公钥(Public Key)
证书信息(如域名、有效期)
CA 的签名(如果是受信任证书)

如果用 OpenSSL 查看 .crt 文件,会发现它不只是公钥:
openssl x509 -in server.crt -text -noout
其中会显示 证书颁发机构(Issuer)、有效期、使用限制 等。

openssl x509 -in server.crt -pubkey -noout > server.pub
这样 server.pub 才是单纯的公钥。


# nginx 加载证书重启报错
SSL: error:0A00018F:SSL routines::ee key too small 表示 SSL/TLS 连接失败。
可能的原因是私钥长度过短,现代 SSL/TLS 需要 至少 2048 位 的 RSA 私钥。
之前没加长度参数,默认是1024

# 查看私钥长度
openssl rsa -in server.key -text -noout | grep "Private-Key"

openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048   # 后面加上长度,默认1024
genpkey         生成私钥(支持多种算法,包括 RSA、ECDSA、Ed25519)。
-algorithm RSA  指定密钥算法为 RSA。
-out server.key 生成的私钥存储在 server.key 文件中。
-pkeyopt rsa_keygen_bits:2048  指定 RSA 密钥长度为 2048 位。


# 关于 SAN (Subject Alternative Name) 主题备用名称。
它是 X.509 证书扩展字段,用于指定多个域名或IP 地址,使证书能适用于多个网站或服务器。例如:
example.com
www.example.com
sub.example.com
192.168.1.100

如果颁发证书时没有配置SAN信息,Chrome 和 Firefox 会报“证书无效”,哪怕 CN 是正确的。
尤其是在 2020 年后所有现代浏览器都不再信任仅带 CN 的证书。

chrome提示:
此服务器无法证实它就是 x.x.com - 它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。

# 查看证书中的SAN信息
openssl x509 -in server.crt -noout -text
可以看到关于SAN字段的信息
略···
X509v3 Subject Alternative Name: 
	DNS:x.com, DNS:entain.x.com, IP Address:127.0.0.1
略···

通过openssl命令查看了一个Let's Encrypt颁发的证书,其中此字段的值和CN字段值一致。
在实际应用中,直接保持两者一致即可,当然SAN中可以写多个(也就是云平台中卖的 多域名证书)。

2025-06-19
发表者 Venus
自签名证书生成步骤已关闭评论

自签名证书生成步骤

流程分为3步:生成私钥 – 生成CSR – 自己颁发证书

# 1、生成RSA私钥
[root@docker-server cert]# openssl genrsa -out server.key 2048
openssl          OpenSSL工具,用于处理加密和证书管理。
genrsa           生成 RSA 私钥(PKCS#1 格式)。
-out server.key  指定输出文件 server.key(存储私钥)。
2048             指定密钥长度为 2048 位(常见长度包括 2048、3072、4096 位)。

建议2048以上,1024在nginx中重启时会提示错误:长度过小。

#  server.key 内容
-----BEGIN RSA PRIVATE KEY-----
···
···
···
-----END RSA PRIVATE KEY-----

私钥的编码格式通常分为 PKCS#1 和 PKCS#8。
PKCS#1 是 RSA 密钥结构标准,PKCS#1私钥通常使用 PEM 格式存储。
PEM(Privacy-Enhanced Mail)文件是 Base64 编码的文本格式。

PS:使用 genpkey 命令生成 PKCS#8 格式的 RSA 私钥
[root@docker-server cert]# openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
# server.key 内容
-----BEGIN PRIVATE KEY-----
···
···
···
-----END PRIVATE KEY-----

PKCS#8 和 PKCS#1 私钥格式可以互相转换。

# 2、生成csr(Certificate Signing Request证书签名请求)
[root@docker-server cert]# openssl req -new -key server.key -out server.csr
生成证书签名请求(CSR),CSR 是向 证书颁发机构(CA) 申请 SSL/TLS 证书时提交的文件。
openssl req      调用 OpenSSL 的 req(Request)模块,用于处理证书请求 csr。
-new             生成一个新的 CSR(不是已有证书的更新)。
-key server.key  使用 server.key 私钥生成 CSR,公钥通过私钥计算得出。
-out server.csr  生成的证书签名请求(CSR)保存到 server.csr 文件。

使用私钥计算出公钥,生成的CSR中会包含主体信息、公钥,用于将来签名。

填写证书信息,需输入:
国家(C):如 CN
省份(ST):如 Shandong
城市(L):如 Jinan
组织(O):如 YourCompanyName
部门(OU):如 IT
通用名称(CN):如 dev.domain.com
邮箱(emailAddress):如 dev@mail.com

将生成的server.csr提交给CA,CA通过它签发证书。自己作为ca角色的话,就自己签发。


# 3、颁发证书
[root@docker-server cert]# openssl x509 -req -in server.csr -signkey server.key -out server.crt -days 365
参数	            说明
-req	            表示使用的是 CSR 输入
-in server.csr	    输入的 CSR 文件
-signkey server.key	使用哪个私钥签发(此处的签名者和持有者相同)
-out server.crt	    输出生成的证书
-days 365	        有效期
这样生成的 server.crt 就是自签名证书,它的签名者就是它自己。
客户端(如浏览器)默认不信任它,除非你导入它为“受信任根证书”。

总结最后得到3个文件:
server.key 私钥
server.csr 证书签名请求 csr
server.crt 颁发的证书


# 其它
# 一条命令直接生成私钥和公钥
[root@docker-server a]# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/C=CN/ST=SHANDONG/L=JINAN/O=GAO DE TECH/OU=IT/CN=dev.xxx.com'
-nodes 是no des加密

# 提取查看公钥内容
[root@docker-server ca]# openssl x509 -in server.crt -noout -pubkey

# 查看证书信息
[root@docker-server ca]# openssl x509 -in server.crt -noout -text

2025-06-13
发表者 Venus
php使用自签名证书调用三方接口已关闭评论

php使用自签名证书调用三方接口

自己生成私钥和csr,将csr发给对方,对方为私有ca,给我们颁发证书(公钥),php代码需要配置证书、根证书及私钥访问对方接口。

对方给的证书只有服务器证书,没有给根证书,可以访问对方域名提取,或者命令行获取。

openssl s_client -connect x.x.xgaming.com:443 -showcerts


命令输出的比较多,通过判断 “CN =” 字段来确认是服务器证书、还是中间证书或者根证书。

用浏览器方式导出根证书最方便。

// 设置对方CA根证书(验证服务器身份)
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/ca.crt");
// 设置客户端证书和私钥(双向TLS用)
curl_setopt($ch, CURLOPT_SSLCERT, __DIR__ . "/prod-cert.pem");
curl_setopt($ch, CURLOPT_SSLKEY, __DIR__ . "/PrivateKey.key");

CURLOPT_SSLCERT → 向服务器提供客户端证书(公钥)。
CURLOPT_SSLKEY → 客户端私钥,用于 解密服务器返回的加密数据。
CURLOPT_CAINFO → 用于验证服务器的证书是否可信。

双向tls流程参考:
https://help.aliyun.com/zh/api-gateway/traditional-api-gateway/user-guide/mutual-tls-authentication
PS:通过 https://decoder.link/result 这个网站可以解析证书内容。

为什么要对方颁发证书给我们?因为对方是根ca,可以免去对方要求自己提供根ca证书的步骤。
# 可以通过下面命令测试mtls
openssl s_client -connect api.example.com:443 -cert client.crt -key client.key -CAfile ca.crt

2025-04-28
发表者 Venus
通过udev修改/dev/下的设备权限已关闭评论

通过udev修改/dev/下的设备权限

admin@rd-GMB5188:~$ ll /dev/gpcdrv 
crw------- 1 root root 236, 0 Apr 27 21:00 /dev/gpcdrv

默认此设备只有root账户可以读写,其它账号无法使用,通过udev规则实现自动修改。

# 查看设备属性等信息
root@rd-GMB5188:~# udevadm info -a -n /dev/gpcdrv 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/virtual/gpcdrv/gpcdrv':
    KERNEL=="gpcdrv"
    SUBSYSTEM=="gpcdrv"
    DRIVER==""
    ATTR{power/async}=="disabled"
    ATTR{power/control}=="auto"
    ATTR{power/runtime_active_kids}=="0"
    ATTR{power/runtime_active_time}=="0"
    ATTR{power/runtime_enabled}=="disabled"
    ATTR{power/runtime_status}=="unsupported"
    ATTR{power/runtime_suspended_time}=="0"
    ATTR{power/runtime_usage}=="0"


# 确定可以通过KERNEL和SUBSYSTEM属性匹配设备进行修改权限。
root@rd-GMB5188:~# cat /etc/udev/rules.d/98-gpcdrv.rules 
KERNEL=="gpcdrv", SUBSYSTEM=="gpcdrv", MODE="0664"

# 重启后再次查看权限
admin@rd-GMB5188:~$ ll /dev/gpcdrv 
crw-rw-r-- 1 root root 235, 0 Apr 27 21:05 /dev/gpcdrv