文章目录
- 说明
- 示例(公网上的公开web)
-
- 安装SSL证书
-
- [Certbot 的 Webroot 模式 和 Standalone 模式的区别](#Certbot 的 Webroot 模式 和 Standalone 模式的区别)
-
- [**Webroot 模式**](#Webroot 模式)
- [**Standalone 模式**](#Standalone 模式)
- 技术对比表
- [Node.js 场景下的最佳实践](#Node.js 场景下的最佳实践)
-
- [推荐方案:**Webroot 模式**](#推荐方案:Webroot 模式)
- [Standalone 模式应急使用:](#Standalone 模式应急使用:)
- [为什么 Standalone 不需要路径?深层解释](#为什么 Standalone 不需要路径?深层解释)
- 实际应用建议
- 修改web应用的代码
- 启动web应用
- 示例(内网中的web)
-
- 建立证书配置文件。
-
- SSL/TLS证书配置文件
- [**1. 基础字段模块 `[req]`**](#1. 基础字段模块
[req]
) - [**2. 专有名称模块 `[dn]` 或 `[req_dn]`**](#2. 专有名称模块
[dn]
或[req_dn]
) - [**3. X.509扩展模块**](#3. X.509扩展模块)
-
- [**(1) 基本扩展 `[v3_ca]`**](#(1) 基本扩展
[v3_ca]
) - [**(2) 服务器证书扩展 `[v3_req]`**](#(2) 服务器证书扩展
[v3_req]
) - [**(3) 客户端证书扩展 `[v3_client]`**](#(3) 客户端证书扩展
[v3_client]
)
- [**(1) 基本扩展 `[v3_ca]`**](#(1) 基本扩展
- [**4. 扩展字段详解**](#4. 扩展字段详解)
-
- [**(1) `keyUsage`(密钥用途)**](#(1)
keyUsage
(密钥用途)) - [**(2) `extendedKeyUsage`(扩展密钥用途)**](#(2)
extendedKeyUsage
(扩展密钥用途)) - [**(3) `subjectAltName`(主题备用名称)**](#(3)
subjectAltName
(主题备用名称)) - [**(4) `basicConstraints`(基本约束)**](#(4)
basicConstraints
(基本约束))
- [**(1) `keyUsage`(密钥用途)**](#(1)
- [**5. 高级扩展**](#5. 高级扩展)
-
- [**(1) CRL与OCSP配置**](#(1) CRL与OCSP配置)
- [**(2) 证书策略(Certificate Policies)**](#(2) 证书策略(Certificate Policies))
- [**(3) 增强密钥用法(自定义OID)**](#(3) 增强密钥用法(自定义OID))
- [**6. 完整配置文件示例**](#6. 完整配置文件示例)
- [**7. 注意事项**](#7. 注意事项)
- 生成证书。
- 客户端安装证书
- 无证书配置文件,直接生成证书
说明
日期:2025年5月30日
与以纯文本形式发送和接收消息的标准 HTTP 不同,HTTPS 使用SSL/TLS等协议对服务器进行身份验证、加密通信内容和检测篡改。 这样可以防止欺骗、中间人攻击和窃听等攻击。
SSL/TLS证书(以下简称证书)很重要,如果用户主动信任了伪造证书,那https的优势就荡然无存了,所以不要自己添加证书。
示例(公网上的公开web)
日期:2025年5月30日。
操作系统:Alibaba Cloud Linux 3.2104 LTS 64位。
应用:
- node.js v22.15.1
- npm v11.4.1
- Certbot
安装SSL证书
公开的证书必须使用固定域名或固定公网ip。
示例中使用域名fxxkrock.top
。
修改时区,有的linux时区不是中国,SSL证书含有证书起止时间,所以申请SLL证书后修改时间可能导致证书失效。
bash
sudo timedatectl set-timezone Asia/Shanghai
添加 EPEL 仓库(Certbot 依赖)
bash
sudo yum install -y epel-release
报错
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ sudo yum install -y epel-release
Last metadata expiration check: 15:18:43 ago on Thu 29 May 2025 08:17:50 PM CST.
Error:
Problem: problem with installed package epel-aliyuncs-release-8-15.1.al8.noarch
- package epel-aliyuncs-release-8-15.1.al8.noarch from @System conflicts with epel-release provided by epel-release-8-22.el8.noarch from epel
- package epel-aliyuncs-release-8-15.1.al8.noarch from alinux3-updates conflicts with epel-release provided by epel-release-8-22.el8.noarch from epel
- conflicting requests
(try to add '--allowerasing' to command line to replace conflicting packages or '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
这个错误是因为系统中已经存在名为 epel-aliyuncs-release
的包,与标准的 epel-release
包冲突。
从包的名称来看,是阿里云自己兼容的epel,所以直接进行下一步。
安装certbot。
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ sudo yum install -y certbot
使用 Standalone 模式(需临时停止占用 80/443 端口的服务),获取SSL证书。
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ ~]$ sudo certbot certonly --standalone -d fxxkrock.top
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): [email protected]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n
Account registered.
Requesting a certificate for fxxkrock.top
Certbot failed to authenticate some domains (authenticator: standalone). The Certificate Authority reported these problems:
Domain: fxxkrock.top
Type: connection
Detail: 47.97.27.78: Fetching http://fxxkrock.top/.well-known/acme-challenge/DqitmUHBr-4eEkBcNWoEZWzAf10C8Gwpm5ipvFxoY1U: Timeout during connect (likely firewall problem)
Hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
报错了。从提示看,也就是网不通,要从80端口访问。
Certbot 的 Webroot 模式 和 Standalone 模式的区别
Webroot 模式
工作原理:
- 在您的网站根目录创建临时验证文件(
/.well-known/acme-challenge/
)- Let's Encrypt 服务器通过 HTTP 访问这些文件验证域名所有权
- 需要指定网站根目录路径 (如
-w /var/www/your-site
)为什么需要路径:
- Certbot 需要将验证文件写入指定目录
- Web 服务器(Nginx/Apache/Node.js)必须能通过 HTTP 80 端口访问这些文件
- 例如:
http://your-domain.com/.well-known/acme-challenge/xxxxx
优势:
- 无需停止正在运行的 Web 服务
- 适合生产环境(服务持续可用)
- 可与现有 Web 服务器配合使用
适用场景:
- 已有 Web 服务器运行中
- 无法临时停止服务
- 可访问网站根目录
Standalone 模式
工作原理:
- Certbot 自己启动临时 Web 服务器(监听 80/443 端口)
- 直接响应 Let's Encrypt 的验证请求
- 无需指定路径
为什么不需要路径:
- Certbot 完全自己处理验证请求
- 不依赖现有 Web 服务器或文件系统
- 验证过程在内存中完成,不写入文件
优势:
- 简单快速,无需配置 Web 服务器
- 不依赖现有网站目录结构
- 适合无 Web 服务器的环境
代价:
- 需临时停止占用 80/443 端口的服务
- 获取证书期间服务短暂中断
- 不适合 7x24 小时运行的关键服务
技术对比表
特性 Webroot 模式 Standalone 模式 需要路径 ✓ (必须指定网站根目录) ✗ (完全自包含) 需停止服务 ✗ ✓ (释放80/443端口) 验证方式 通过现有Web服务器访问文件 自建临时Web服务器响应请求 适合场景 生产环境/服务不可中断 测试环境/简单快速获取证书 依赖Web服务器 ✓ (需配置访问.well-known目录) ✗ 证书续期影响 零中断 短暂中断(约10-30秒)
Node.js 场景下的最佳实践
推荐方案:Webroot 模式
bash# 1. 创建验证目录 sudo mkdir -p /var/www/ssl_validation/.well-known/acme-challenge # 2. 在Node.js中添加路由处理验证 const app = express(); app.get('/.well-known/acme-challenge/:token', (req, res) => { res.sendFile(`/var/www/ssl_validation/.well-known/acme-challenge/${req.params.token}`); }); # 3. 获取证书 sudo certbot certonly --webroot -w /var/www/ssl_validation -d your-domain.com
Standalone 模式应急使用:
bash# 1. 停止Node.js服务 sudo systemctl stop node-app # 2. 获取证书(Standalone模式) sudo certbot certonly --standalone -d your-domain.com --preferred-challenges http # 3. 重启服务 sudo systemctl start node-app
为什么 Standalone 不需要路径?深层解释
Standalone 模式的工作流程:
Certbot 启动内置的微型 HTTP 服务器(Python实现)
监听 80 端口(HTTP验证)或 443 端口(TLS-ALPN验证)
当 Let's Encrypt 发送验证请求时:
LE Server Certbot 请求 http://domain.com/.well-known/acme-challenge/token123 即时生成并返回验证内容 LE Server Certbot
验证通过后立即销毁临时服务器
全程不涉及文件系统操作,所有验证内容在内存中动态生成
这种设计使得 Standalone 模式:
- 完全独立于现有 Web 基础设施
- 不需要配置任何文件路径
- 但要求独占端口(需临时停止其他服务)
实际应用建议
对于 Node.js 项目,推荐组合方案:
首次获取证书:使用 Standalone 模式(简单快速)
bashsudo systemctl stop node-app sudo certbot certonly --standalone -d your-domain.com sudo systemctl start node-app
证书续期:改用 Webroot 模式(无中断)
javascript// 在Express中添加验证路由 app.use('/.well-known/acme-challenge', express.static('/etc/letsencrypt/webrootauth'));
bash# 续期配置 sudo certbot renew --webroot -w /etc/letsencrypt/webrootauth
终极方案:用 Nginx 处理验证(最佳实践)
nginxserver { listen 80; server_name your-domain.com; location /.well-known/acme-challenge { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } }
这样 Node.js 只需专注 443 端口 HTTPS 服务,完全解耦证书管理。
从资料看,在过程中,80/443 端口都要使用。
安全设备进出都开启80/443。
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ ~]$ sudo certbot certonly --standalone -d fxxkrock.top
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for fxxkrock.top
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/fxxkrock.top/fullchain.pem
Key is saved at: /etc/letsencrypt/live/fxxkrock.top/privkey.pem
This certificate expires on 2025-08-28.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
需要记录其中 Certificate 和 Key 的保存位置,web应用需要加载这两个文件。
修改web应用的代码
javascript
// 添加https模块
const https = require('https');
// 读取SSL证书文件
const credentials = {
key: fs.readFileSync('/etc/letsencrypt/live/fxxkrock.top/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/fxxkrock.top/fullchain.pem')
};
// 设置端口号
const port = 3080;
// 创建HTTPS服务器
const server = https.createServer(credentials, app).listen(port, () => {
console.log(`HTTPS server successfully launched: https://localhost:${port}`);
});
启动web应用
权限不够,无法读取SSL证书
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ node server.js
node:fs:562
return binding.open(
^
Error: EACCES: permission denied, open '/etc/letsencrypt/live/fxxkrock.top/privkey.pem'
at Object.openSync (node:fs:562:18)
at Object.readFileSync (node:fs:446:35)
at Object.<anonymous> (/home/ecs-user/server_crystalsearch/server.js:103:13)
at Module._compile (node:internal/modules/cjs/loader:1730:14)
at Object..js (node:internal/modules/cjs/loader:1895:10)
at Module.load (node:internal/modules/cjs/loader:1465:32)
at Function._load (node:internal/modules/cjs/loader:1282:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:170:5) {
errno: -13,
code: 'EACCES',
syscall: 'open',
path: '/etc/letsencrypt/live/fxxkrock.top/privkey.pem'
}
Node.js v22.15.1
复制这两证书到网站目录,并修改js代码,把文件路径改为新路径。
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ sudo cp /etc/letsencrypt/live/fxxkrock.top/privkey.pem /home/ec
s-user/server_crystalsearch/privkey.pem
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ sudo cp /etc/letsencrypt/live/fxxkrock.top/fullchain.pem /home/
ecs-user/server_crystalsearch/fullchain.pem
启动过程无报错
bash
[ecs-user@iZbp18zmckjuyndr4e25koZ server_crystalsearch]$ node server.js
Web folder: /home/ecs-user/server_crystalsearch/crystalsearch
HTTPS server successfully launched: https://localhost:3060
浏览器访问http://fxxkrock.top:3060/
,浏览器显示"响应时间过长"。
访问https://fxxkrock.top:3060/
,浏览器显示"响应时间过长"。
忘记在安全设备打开3060端口了。
打开后,https正常,控制台无报错。
访问http会自动跳转到https。
示例(内网中的web)
日期:2025年5月30日。
操作系统:ubuntu server v24.04.2 amd64。
ip:192.168.3.10。
在内网中自己生成证书,先要给服务器固定ip,因为整数中含有ip地址,生成要比后,需要在客户端中导入书证。
建立证书配置文件。
新建文件ssl.conf
,输入以下内容。
bash
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
x509_extensions = v3_req
[dn]
CN = 192.168.3.71
[v3_req]
keyUsage = keyEncipherment, dataEncipherment, digitalSignature
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.3.10
SSL/TLS证书配置文件
在SSL/TLS证书配置文件(如OpenSSL的
.conf
文件)中,可以定义大量字段和扩展参数来精确控制证书的属性和行为。以下是SSL配置文件的核心模块及其详细说明,涵盖基本字段、X.509扩展和高级选项。
1. 基础字段模块
[req]
定义证书请求(CSR)的全局参数:
conf[req] default_bits = 2048 # 密钥长度(2048/4096) default_md = sha256 # 哈希算法(sha256/sha384) prompt = no # 是否交互式输入(no表示自动填充) distinguished_name = req_dn # 关联的DN(专有名称)配置块 req_extensions = v3_req # 使用的扩展模块 encrypt_key = no # 是否加密私钥(no表示不加密)
2. 专有名称模块
[dn]
或[req_dn]
定义证书的**主题(Subject)**信息,通常用于标识实体:
conf[dn] countryName = CN # 国家代码(2字母,如CN/US) stateOrProvinceName = Guangdong # 省份/州 localityName = Shenzhen # 城市 organizationName = My Company # 组织名称 organizationalUnitName = IT Department # 部门名称 commonName = 192.168.3.71 # 通用名(域名或IP) emailAddress = [email protected]# 联系邮箱(可选)
字段说明
字段名 用途 countryName
国家代码(ISO 3166-1标准,如CN/US/JP) stateOrProvinceName
省份或州(需与注册实体一致) localityName
城市或地区名称 organizationName
组织全称(如公司名) organizationalUnitName
部门名称(如IT/Sales) commonName
证书主体标识(对服务器证书为域名或IP地址) emailAddress
管理员邮箱(通常用于客户端证书或代码签名证书)
3. X.509扩展模块
(1) 基本扩展
[v3_ca]
用于定义证书颁发机构(CA)证书的属性:
conf[v3_ca] subjectKeyIdentifier = hash # 标识证书公钥的哈希值 authorityKeyIdentifier= keyid:always,issuer:always # 关联上级CA的公钥标识 basicConstraints = CA:TRUE # 标记此证书为CA证书 keyUsage = critical, cRLSign, keyCertSign # 密钥用途(仅CA)
(2) 服务器证书扩展
[v3_req]
用于普通服务器或终端实体证书:
conf[v3_req] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer basicConstraints = CA:FALSE # 非CA证书 keyUsage = digitalSignature, keyEncipherment # 密钥用途 extendedKeyUsage = serverAuth, clientAuth # 扩展用途(服务器/客户端) subjectAltName = @alt_names # 主题备用名(SAN)
(3) 客户端证书扩展
[v3_client]
用于客户端身份验证:
conf[v3_client] extendedKeyUsage = clientAuth # 限制证书仅用于客户端认证
4. 扩展字段详解
(1)
keyUsage
(密钥用途)定义证书密钥允许的操作,需标记为
critical
时表示强制遵守:
confkeyUsage = digitalSignature, keyEncipherment, dataEncipherment
值 用途 digitalSignature
允许用于数字签名(如TLS握手) keyEncipherment
允许加密传输的对称密钥(用于RSA密钥交换) dataEncipherment
允许直接加密数据(极少使用) keyAgreement
允许密钥协商(如ECDH密钥交换) crlSign
允许签发CRL(证书吊销列表) keyCertSign
允许签发下级证书(仅CA证书) (2)
extendedKeyUsage
(扩展密钥用途)限制证书的具体应用场景:
confextendedKeyUsage = serverAuth, codeSigning, emailProtection
值 用途 serverAuth
用于服务器身份验证(HTTPS) clientAuth
用于客户端身份验证(双向TLS) codeSigning
用于代码签名(如软件发布) emailProtection
用于邮件加密或签名(S/MIME) timeStamping
用于时间戳服务 (3)
subjectAltName
(主题备用名称)定义证书支持的域名、IP或URI列表:
conf[alt_names] DNS.1 = example.com DNS.2 = *.example.com IP.1 = 192.168.3.71 email.1 = [email protected] URI.1 = http://example.com/resource
(4)
basicConstraints
(基本约束)控制证书是否可作为CA证书:
confbasicConstraints = critical, CA:TRUE, pathlen:0
CA:TRUE
:允许签发下级证书。pathlen:0
:下级CA最多只能签发终端实体证书(不能有孙级CA)。
5. 高级扩展
(1) CRL与OCSP配置
定义证书吊销信息分发点:
confcrlDistributionPoints = URI:http://crl.example.com/root.crl authorityInfoAccess = caIssuers;URI:http://certs.example.com/ca.crt, OCSP;URI:http://ocsp.example.com
(2) 证书策略(Certificate Policies)
声明证书的使用策略(通常用于EV证书):
confcertificatePolicies = 1.3.6.1.4.1.12345.1.2.3
(3) 增强密钥用法(自定义OID)
支持自定义扩展:
conf1.3.6.1.4.1.311.20.2 = ASN1:UTF8String:Microsoft Individual Code Signing
6. 完整配置文件示例
conf[req] default_bits = 2048 default_md = sha256 prompt = no distinguished_name = req_dn req_extensions = v3_req [req_dn] countryName = CN stateOrProvinceName = Guangdong localityName = Shenzhen organizationName = My Corp commonName = 192.168.3.71 [v3_req] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] IP.1 = 192.168.3.71 DNS.1 = internal-server
7. 注意事项
- 兼容性:旧版浏览器(如IE6)可能不支持SHA-256或SAN扩展。
- 安全性 :优先使用
sha256
及以上算法,密钥长度≥2048位。- 强制标记 :若扩展字段标记为
critical
,客户端必须理解该扩展否则拒绝证书。- 私有IP限制:公共CA不会为私有IP签发证书,需自签名或使用内部CA。
通过灵活组合这些字段和扩展,可以生成符合特定场景需求的安全证书。
生成证书。
bash
zzs@testser:~$ zzs@testser:~$ openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 3650 -config ssl.conf -extensions v3_req
..+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..............+.+.....+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+......+...............+..+.......+...+.....+...+.........+.+......+.....+...+.......+.....+.+............................................+...+......+.+......+.........+.....+...+.+...........+...+.+..+...+....+...+........+...................+.....+..........+.....+......+............+....+.....+.+..+.+.....+.........+.......+.....+.+...............+...+..+.........+.+...+...........+...+.+.........+.....+.+..+...+....+..................+...+.....+......+...+...+....+.....+......+.........+...............+...+.+.....+.+.........+.....+.......+.........+......+............+.....+...+....+.....+....+.....+....+..+.+..+...+....+...+.....+..................+...+....+..+.+...+......+...........+.........+...+.......+......+...+.....+.........+.+......+.....+...+.+.....+....+.....+..........+.....+.+.....+.+......+.....+..................+..........+..+.............+..+....+...+........+.......+......+......+...+.....+............+.+.....+..........+..+..........+..+....+.........+......+......+...+.....+...+.......+..................+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.+.+..+...+.+..............+.+...+.....+......+.+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+....+..+.........+.......+..+.+.....+....+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+.+.....+.+.........+..+.......+...+........+.+...+...............+.....+............+......+...+............+...+.+.....+...+.+.....+.......+............+..+.+.....+..........+..............+..........+.....+..........+......+...+..+...+.......+.........+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
zzs@testser:~$ dir
server.crt server.key ssl.conf
会多出两个文件:
server.key
: 私钥文件server.crt
: 证书文件
客户端安装证书
以windows为例,把server.crt
发送到客户端→ 双击 server.crt
→ 选择"安装证书" → 存储位置为"本地计算机" → 选择"受信任的根证书颁发机构"。
无证书配置文件,直接生成证书
如果对证书内容无要求,可以不使用证书配置文件,直接在命令中指定ip,即可生成证书。
bash
zzs@testser:~/aaa$ openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 3650 -subj "/CN=192.168.3.10" -addext "subjectAltName=IP:192.168.3.10"
..+...+....+..+...+.+.........+........+...............+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+.+.....+.......+..+......+....+........+...+.........+...+....+.....+.........+....+......+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...........+.....+...+.......+..+....+.....+.......+...+....................+....+......+..+.........+....+......+......+............+...+........+...............+.........+...+............+.+..............+..........+..+...............+.+.....+....+...+...+.....+...+....+........+.........+...+.......+...+..+....+..............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
..+.....+......+......+.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.........+...........+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..........+.+........+.......+...........+...+......+.+..+.......+...+.....+.+..+..........+..+.......+...+..+...............+.+...+.....+......+..........+...+..+................+...+...........+......+............+......+......+.+..+.............+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
zzs@testser:~/aaa$ dir
server.crt server.key