Chemmy's Blog

chengming0916@outlook.com

PKCS#12(.p12 或 .pfx)是一种常用的证书封装格式,通常包含私钥、公钥证书以及可选的CA证书链,并通过密码保护。以下是使用 OpenSSL 生成 PKCS#12 证书的完整流程。

步骤 1:生成私钥

1
openssl genpkey -algorithm RSA -out private.key -aes256

此命令生成一个 2048位RSA私钥 并使用 AES-256 加密,系统会提示输入保护私钥的密码。

步骤 2:生成证书签名请求(CSR)

1
openssl req -new -key private.key -out request.csr

根据提示填写国家、组织、域名等信息,这些将写入证书中。

步骤 3:生成自签名证书

1
2
openssl x509 -req -days 365 -in request.csr \ 
-signkey private.key -out certificate.crt

该命令生成一个有效期为 365天 的自签名 X.509 证书。

步骤 4:导出 PKCS#12 文件

1
2
3
4
5
openssl pkcs12 -export \
-in certificate.crt \
-inkey private.key \
-out certificate.p12 \
-name "MyCert"

执行时会提示输入导出密码,用于保护 .p12 文件中的私钥。

步骤 5:验证 PKCS#12 文件

1
openssl pkcs12 -info -in certificate.p12

可查看 .p12 文件中包含的证书和私钥信息。

最佳实践与提示:

若需包含 CA 链,可在导出时添加 -chain -CAfile ca.crt 参数。

私钥建议使用强加密算法(如 AES-256)并妥善保存。

.p12 文件常用于 HTTPS服务器部署、客户端身份认证 或 代码签名 场景。

这样即可从零生成一个安全的 PKCS#12 格式证书,并可直接用于 Nginx、Tomcat、Java Keystore 等环境。

方法1

最简单的一种方法,将当前用户添加到root组。这样做之后该用户将拥有所有root权限,从而使用户在使用sudo时不再需要输入密码。

1
sudo adduser {当前用户名} root 

注意: 将用户添加到root组后,该用户将拥有最高权限,因此在执行系统级操作时要特别小心,以避免可能的系统破坏。

方法2(推荐)

通过编辑/etc/sudoers文件来配置特定用户或组的sudo行为。这种方法允许更灵活的控制哪些命令可以绕过密码提示。
![[Linux配置sudo无密码/IMG-20250319160639846.png]]

单用户配置

1
{用户名} ALL=(ALL:ALL) NOPASSWD:ALL #在 root 后新添加一行

用户组配置

1
%{用户组} ALL=(ALL:ALL) NOPASSWD:ALL # 在 %sudo 后添加

使用此方式需将用户添加进组

1
sudo usermod -a -G {用户组} {用户名}

安装Golang

Windows版本下载安装程序安装即可,Ubuntu下有两种安装方式
第一种方式

1
2
sudo apt update
sudo apt install golang

此种方式安装的版本并不是最新版,或者下载 [官方包]执行

1
2
sudo tar -zxvf go1.24.2.linux-amd64.tar.gz -C  /usr/local # 解压缩到/usr/local
sudo chmod 755 -R /usr/local/go # 修改权限,一般解压后就有权限,此步可以省略

配置环境变量

Windows

打开 系统设置->关于->高级系统设置->环境变量,注意如果只给当前用户使用添加到用户的环境变量即可,全部用户可用需配置系统环境变量。

GOROOT

![[Golang环境配置/IMG-20250804110742705.png]]

GOPATH
![[Golang环境配置/IMG-20250804110742880.png]]

GOPROXY

![[Golang环境配置/IMG-20250804110743185.png]]

Ubuntu

如果只给当前用户使用编辑用户目录下.bashrc文件,全部用户可用需配置/etc/profile

1
2
3
export GOROOT=/usr/local/go # Golang根目录
export GOPATH=/home/go-project # 项目根目录
export PATH=$GOROOT/bin:$GOPATH/bin:$PATH

进阶配置

GOPROXY可在环境变量中配置也可使用go env -w命令配置

1
2
3
go env -w GOPROXY=https://goproxy.cn # 七牛
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/ # 阿里
go env -w GOPROXY=https://goproxy.io # 官方

GO111MODULE
从go 1.11版本开始,推荐使用Go Modules进行包管理。

1
go env -w GO111MODULE=on

在项目目录下初始化模块

1
go mod init 

1. 第一个Qt程序

1.1 Hello Qt

1
2
3
4
5
6
7
8
9
10
#include <QApplication>          // 头文件引用, 每个Qt类都有对应的头文件,类的定义
#include <QLabel> // 包含了对该类的定义

int main(int argc, char *argv[])
{
QApplication app(argc, argv); // 创建QApplication对象,管理整个应用
QLabel *label = new QLabel("Hello Qt"); // QLabel部件,用于显示
label->show(); // # 使QLabel部件可见
return app.exec(); // 将应用程序的控制权传递给Qt,程序等待用户操作
}

测试程序

图片占位

在源码根目录打开命令提示符执行qmake -project生成hello.pro项目文件,然后执行qmake hello.pro从这个项目文件生成makefile文件,在输入make命令就可以构建该应用。

方式一、虚拟ip访问

安装docker时,docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问。

1
2
3
4
5
6
7
8
9
10
11
# ifconfig
---
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:35ff:feac:66d8 prefixlen 64 scopeid 0x20<link>
ether 02:42:35:ac:66:d8 txqueuelen 0 (Ethernet)
RX packets 4018 bytes 266467 (260.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4226 bytes 33935667 (32.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
---

运行一个centos镜像, 查看ip地址得到:172.17.0.7

1
2
3
4
5
6
7
8
9
10
11
12
13
# docker run -it --name centos-1 docker.io/centos:latest
# ifconfig

---
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.7 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:7 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:07 txqueuelen 0 (Ethernet)
RX packets 16 bytes 1296 (1.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
---

以同样的命令再起一个容器,查看ip地址得到:172.17.0.8

1
2
3
4
5
6
7
8
9
10
11
12
13
# docker run -it --name centos-2 docker.io/centos:latest
# ifconfig

---
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.8 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:8 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:08 txqueuelen 0 (Ethernet)
RX packets 8 bytes 648 (648.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
---

容器内部ping测试结果如下:

1
2
3
4
5
6
7
8
9
# ping 172.17.0.7

---
PING 172.17.0.7 (172.17.0.7) 56(84) bytes of data.
64 bytes from 172.17.0.7: icmp_seq=1 ttl=64 time=0.205 ms
64 bytes from 172.17.0.7: icmp_seq=2 ttl=64 time=0.119 ms
64 bytes from 172.17.0.7: icmp_seq=3 ttl=64 time=0.118 ms
64 bytes from 172.17.0.7: icmp_seq=4 ttl=64 time=0.101 ms
---

这种方式必须知道每个容器的ip,在实际使用中并不实用。

运行容器的时候加上参数link

运行第一个容器

1
docker run -it --name centos-1 docker.io/centos:latest

运行第二个容器

1
2
3
docker run -it --name centos-2 \ 
--link centos-1:centos-1 \
docker.io/centos:latest

--link:参数中第一个centos-1是 容器名 ,第二个centos-1是定义的 容器别名 (使用别名访问容器),为了方便使用,一般别名默认容器名。

测试结果如下:

1
2
3
4
5
6
7
8
9
# ping centos-1

---
PING centos-1 (172.17.0.7) 56(84) bytes of data.
64 bytes from centos-1 (172.17.0.7): icmp_seq=1 ttl=64 time=0.210 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=4 ttl=64 time=0.114 ms
---

此方法对容器创建的顺序有要求,如果集群内部多个容器要互访,使用就不太方便。

方式三、创建bridge网络

  1. 安装好docker后,运行如下命令创建bridge网络:
1
docker network create testnet

查询到新创建的bridge testnet。

  1. 运行容器连接到testnet网络。
    使用方法:
    1
    2
    3
    docker run -it --name <容器名> \
    --network <bridge> \
    --network-alias <网络别名> <镜像名>
1
2
3
4
docker run -it --name centos-1 --network testnet \
--network-alias centos-1 docker.io/centos:latest
docker run -it --name centos-2 --network testnet \
--network-alias centos-2 docker.io/centos:latest
  1. 从一个容器ping另外一个容器,测试结果如下:
1
2
3
4
5
6
7
8
9
# ping centos-1

---
PING centos-1 (172.20.0.2) 56(84) bytes of data.
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=1 ttl=64 time=0.158 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=4 ttl=64 time=0.113 ms
---
  1. 若访问容器中服务,可以使用这用方式访问 <网络别名>:<服务端口号>

推荐使用这种方法,自定义网络,因为使用的是网络别名,可以不用顾虑ip是否变动,只要连接到docker内部bright网络即可互访。bridge也可以建立多个,隔离在不同的网段。

准备

镜像选择

quay.io/coreos/etcd:3.2.7
bitname/etcd

创建ETCD数据目录

1
2
3
# data 存储容器持久化数据
# config 存储容器使用的配置文件
mkdir -p /usr/local/docker/etcd/{data,config}

创建ETCD配置文件

配置文件路径为 /usr/local/docker/etcd/config/etcd.config.yml

1
2
3
4
5
6
7
8
9
10
11
12
name: etcd # etcd member 名称,可根据实际情况修改
data-dir: /var/etcd #etcd 数据目录,可根据实际情况修改
listen-client-urls: http://0.0.0.0:2379 #client 流量监听地址,没特殊需求按文档填写即可
advertise-client-urls: http://0.0.0.0:2379 # 该 member 向外部通告的客户端 url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP
listen-peer-urls: http://0.0.0.0:2380 # peer 流量监听地址,没特殊需求按文档填写即可
initial-advertise-peer-urls: http://0.0.0.0:2380 # 该 member 向同一集群内其他 member 通告的 peer url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP
initial-cluster: etcd=http://0.0.0.0:2380 # 初始化集群节点信息,单节点部署时不需要修改,集群部署模式需要填写集群中所有 member 的信息
initial-cluster-token: etcd-cluster # 初始化集群时使用的 token,随便写
initial-cluster-state: new # 初始化集群状态,可选的值为 **new** 或者 **existing**,通常采用 **new**
logger: zap
log-level: info
# log-outputs: stderr

创建并启动ETCD服务

1
docker run -d --name etcd -p 2379:2379 -p 2380:2380 -v /usr/local/docker/etcd/data:/var/etcd -v /usr/local/docker/etcd/config:/var/lib/etcd/config quay.io/coreos/etcd: 3.5.12 

使用docker-compose部署

创建Docker-compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3'

services:
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.5.12
command: /usr/local/bin/etcd --config-file=/var/lib/etcd/config/etcd.conf.yml
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/lib/etcd
- ${DOCKER_VOLUME_DIRECTORY:-.}/config/etcd.config.yml:/var/lib/etcd/conf/etcd.conf.yml
ports:
- 2379:2379
- 2380:2380
restart: always

networks: # 船舰一个新的bridge模式网络,名称 etcd-tier,名称可以根据需求自定义
default:
name: etcd-tier
driver: bridge

基于环境变量配置, 配置参考配置文件方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: '3'

services:
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.5.12
environment:
- ETCD_NAME=etcd
- ETCD_DATA_DIR=
- ETCD_LISTEN_CLIENT_URLS=
- ETCD_ADVERTISE_CLIENT_URLS=
- ETCD_LISTEN_PEER_URLS=
- ETCD_INSTALL_ADVERTISE_PEER_URLS=
- ETCD_INSTALL_CLUSTER_TOKEN=
- ETCD_INSTALL_CLUSTER
- ETCD_INSTALL_CLUSTER_STATE=new
- ETCD_LOGGER=zap
- ETCD_LOG_LEVEL=info
- ALLOW_NONE_AUTHENTICATION="yes" # 允许无身份验证访问
- TZ="Asia/Shanghai"
volumes:
- ${DOCKER_VOLUME_DIRECTORY:=.}/data:/var/etcd
- /etc/localtime:/etc/localtime:rw
ports:
- 2379:2379
- 2380:2380
restart: always
networks:
default:
name: etcd-tier
driver: bridge

创建并启动etcd

1
2
cd {docker-compose文件所在目录}
docker compose up -d

测试命令

1
2
3
4
5
6
7
8
9
10
11
12
etcdctl --endpoints=192.168.1.2:2379 --write-out=table endpoint health

etcdctl --endpoints=192.168.1.2:2379 --write-out=table endpoint status

# 查看member状态
etcdctl --endpoints=192.168.1.2:2379 --write-out=table member list

# 写入数据
etcdctl --endpoints=192.168.1.2:2379 put foo bar

# 读取数据
etcdctl --endpoints=192.168.1.2:2379 get foo
0%