{{item}}
{{item.title}}
{{items.productName}}
{{items.price}}/年
{{item.title}}
部警SSL证书可实现网站HTTPS加密保护及身份的可信认证,防止传输数据的泄露或算改,提高网站可信度和品牌形象,利于SEO排名,为企业带来更多访问量,这也是网络安全法及PCI合规性的必备要求
前往SSL证书借助Python脚本实现批量配置SSL证书,能够显著提升效率,减少人为错误。本教程将详细介绍如何使用Python脚本完成SSL证书的批量申请、安装与续期。
在开始编写Python脚本前,需对SSL证书和ACME协议有基本了解。SSL证书用于在客户端和服务器之间建立加密连接,确保数据传输安全;ACME协议则是一种用于自动化管理SSL证书的开放标准协议,支持客户端与证书颁发机构(CA)进行交互,实现证书的申请、验证、颁发和续期等操作。目前,Let's Encrypt是使用ACME协议的知名免费CA,其提供的证书适用于大多数场景,我们的教程也将以Let's Encrypt为例进行讲解。
实现批量配置SSL证书,需要安装相关的Python库。其中, certbot 是Let's Encrypt官方推荐的ACME客户端工具, python - certbot 库可在Python脚本中调用 certbot 的功能; dnspython 库用于处理DNS相关操作,在使用DNS - 01挑战方式验证域名所有权时会用到; paramiko 库可实现SSH远程连接,用于在远程服务器上安装和配置证书。通过以下命令安装这些库:
1 pip install certbot python-certbot dnspython paramiko
准备一个包含所有待配置SSL证书域名的列表文件,格式可以为文本文件( .txt ),每行一个域名。例如, domains.txt 文件内容如下:
1 example1.com
2 www.example1.com
3 example2.com
4 www.example2.com
同时,整理好每个域名对应的服务器信息,包括服务器IP地址、SSH用户名和密码(或SSH密钥文件路径)、Web服务器类型(如Apache、Nginx)等。可以将这些信息存储在CSV文件或JSON文件中,方便在脚本中读取。以CSV文件 servers.csv 为例,内容格式如下:
1 domain,ip,username,password,web_server
2 example1.com,192.168.1.100,admin,password123,nginx
3 example2.com,192.168.1.101,user,secret456,apache
HTTP - 01挑战是最常用的域名验证方式,适用于Web服务器可正常对外访问的情况。以下是使用Python脚本基于 certbot 库,通过HTTP - 01挑战批量申请SSL证书的示例代码:
1 import subprocess
2 import csv
3
4 def request_certificates_http01():
5 with open('domains.txt', 'r') as f:
6 domains = f.read().splitlines()
7 with open('servers.csv', 'r') as csvfile:
8 reader = csv.DictReader(csvfile)
9 for row in reader:
10 domain = row['domain']
11 ip = row['ip']
12 username = row['username']
13 password = row['password']
14 web_server = row['web_server']
15 command = f"certbot certonly --standalone -d {domain} --preferred - chain 'ISRG Root X1' --email your_email@example.com --agree - to - terms --no - efail - mitigation"
16 try:
17 subprocess.run(command, shell=True, check=True)
18 print(f"Successfully requested certificate for {domain}")
19 except subprocess.CalledProcessError as e:
20 print(f"Failed to request certificate for {domain}: {e}")
21
22 if __name__ == "__main__":
23 request_certificates_http01()
上述代码中,首先从 domains.txt 文件读取域名列表,从 servers.csv 文件读取服务器信息。然后针对每个域名,构造 certbot 的证书申请命令,使用 subprocess.run 函数执行命令。若命令执行成功,打印成功信息;若失败,打印错误信息。需注意将 your_email@example.com 替换为实际的邮箱地址,该邮箱用于接收证书相关通知。
当Web服务器无法通过HTTP - 01挑战进行验证(如服务器未对外开放80端口)时,可使用DNS - 01挑战。此方式需要通过修改域名的DNS记录来验证域名所有权,以下是示例代码:
1 import subprocess
2 import csv
3 import dns.resolver
4 import time
5
6 def add_dns_txt_record(domain, token):
7 # 此处需根据实际使用的DNS服务商API进行修改
8 # 以Cloudflare为例,需安装`cloudflare - api`库并配置API密钥
9 # 这里仅为示例,实际操作需替换为真实逻辑
10 print(f"Adding TXT record for {domain} with token {token}")
11
12 def remove_dns_txt_record(domain):
13 # 此处需根据实际使用的DNS服务商API进行修改
14 print(f"Removing TXT record for {domain}")
15
16 def request_certificates_dns01():
17 with open('domains.txt', 'r') as f:
18 domains = f.read().splitlines()
19 with open('servers.csv', 'r') as csvfile:
20 reader = csv.DictReader(csvfile)
21 for row in reader:
22 domain = row['domain']
23 ip = row['ip']
24 username = row['username']
25 password = row['password']
26 web_server = row['web_server']
27 command = f"certbot certonly --dns - cloudflare - dns - cloudflare - api - token your_api_token -d {domain} --preferred - chain 'ISRG Root X1' --email your_email@example.com --agree - to - terms --no - efail - mitigation"
28 try:
29 # 获取挑战令牌并添加DNS TXT记录
30 process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
31 stdout, stderr = process.communicate()
32 for line in stdout.decode('utf - 8').splitlines():
33 if "dns - cloudflare - validation - token" in line:
34 token = line.split(': ')[1].strip()
35 add_dns_txt_record(domain, token)
36 # 等待DNS记录生效
37 time.sleep(120)
38 # 执行证书申请命令
39 subprocess.run(command, shell=True, check=True)
40 print(f"Successfully requested certificate for {domain}")
41 # 删除DNS TXT记录
42 remove_dns_txt_record(domain)
43 except subprocess.CalledProcessError as e:
44 print(f"Failed to request certificate for {domain}: {e}")
45
46 if __name__ == "__main__":
47 request_certificates_dns01()
在DNS - 01挑战的代码中,首先获取挑战令牌,调用 add_dns_txt_record 函数添加DNS TXT记录(需根据实际DNS服务商API实现),等待一段时间确保DNS记录生效后,执行证书申请命令,最后删除DNS TXT记录。同样,需将 your_api_token 替换为实际的DNS服务商API令牌, your_email@example.com 替换为真实邮箱地址。
证书申请成功后,需要将证书安装到对应的Web服务器上。以下以Nginx和Apache为例,介绍如何使用Python脚本实现批量安装。
1 import paramiko
2 import csv
3
4 def install_certificates_nginx():
5 with open('servers.csv', 'r') as csvfile:
6 reader = csv.DictReader(csvfile)
7 for row in reader:
8 domain = row['domain']
9 ip = row['ip']
10 username = row['username']
11 password = row['password']
12 web_server = row['web_server']
13 ssh = paramiko.SSHClient()
14 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
15 try:
16 ssh.connect(ip, username=username, password=password)
17 # 备份原有Nginx配置文件
18 stdin, stdout, stderr = ssh.exec_command(f"sudo cp /etc/nginx/sites - available/default /etc/nginx/sites - available/default.bak")
19 # 修改Nginx配置文件以启用HTTPS
20 config = f"""server {{
21 listen 80;
22 server_name {domain};
23 return 301 https://$server_name$request_uri;
24 }}
25 server {{
26 listen 443 ssl;
27 server_name {domain};
28 ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem;
29 ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;
30 include /etc/letsencrypt/options - ssl - nginx.conf;
31 ssl_dhparam /etc/letsencrypt/ssl - dhparams.pem;
32 location / {{
33 # 此处填写Nginx原有配置中的location相关内容
34 }}
35 }}"""
36 sftp = ssh.open_sftp()
37 with sftp.open('/etc/nginx/sites - available/default', 'w') as f:
38 f.write(config)
39 sftp.close()
40 # 重启Nginx服务
41 ssh.exec_command("sudo service nginx restart")
42 print(f"Successfully installed certificate for {domain} on Nginx")
43 except paramiko.AuthenticationException:
44 print(f"Authentication failed for {domain}")
45 except paramiko.SSHException as e:
46 print(f"SSH connection failed for {domain}: {e}")
47 finally:
48 ssh.close()
49
50 if __name__ == "__main__":
51 install_certificates_nginx()
上述代码通过 paramiko 库建立SSH连接到服务器,先备份Nginx原有配置文件,然后将证书路径等相关配置写入Nginx配置文件,最后重启Nginx服务,完成证书安装。
1 import paramiko
2 import csv
3
4 def install_certificates_apache():
5 with open('servers.csv', 'r') as csvfile:
6 reader = csv.DictReader(csvfile)
7 for row in reader:
8 domain = row['domain']
9 ip = row['ip']
10 username = row['username']
11 password = row['password']
12 web_server = row['web_server']
13 ssh = paramiko.SSHClient()
14 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
15 try:
16 ssh.connect(ip, username=username, password=password)
17 # 备份原有Apache配置文件
18 stdin, stdout, stderr = ssh.exec_command(f"sudo cp /etc/apache2/sites - available/000 - default.conf /etc/apache2/sites - available/000 - default.conf.bak")
19 # 修改Apache配置文件以启用HTTPS
20 config = f"""<VirtualHost *:80>
21 ServerName {domain}
22 Redirect permanent / https://{domain}/
23 </VirtualHost>
24 <VirtualHost *:443>
25 ServerName {domain}
26 SSLEngine on
27 SSLCertificateFile /etc/letsencrypt/live/{domain}/fullchain.pem
28 SSLCertificateKeyFile /etc/letsencrypt/live/{domain}/privkey.pem
29 # 此处填写Apache原有配置中的其他相关内容
30 </VirtualHost>"""
31 sftp = ssh.open_sftp()
32 with sftp.open('/etc/apache2/sites - available/000 - default.conf', 'w') as f:
33 f.write(config)
34 sftp.close()
35 # 启用SSL模块并重启Apache服务
36 ssh.exec_command("sudo a2enmod ssl")
37 ssh.exec_command("sudo systemctl restart apache2")
38 print(f"Successfully installed certificate for {domain} on Apache")
39 except paramiko.AuthenticationException:
40 print(f"Authentication failed for {domain}")
41 except paramiko.SSHException as e:
42 print(f"SSH connection failed for {domain}: {e}")
43 finally:
44 ssh.close()
45
46 if __name__ == "__main__":
47 install_certificates_apache()
在Apache服务器安装证书的代码中,同样通过SSH连接服务器,备份配置文件后修改配置以启用HTTPS,启用SSL模块并重启Apache服务,实现证书安装。
SSL证书具有有效期,通常为90天,到期前需要进行续期。Certbot默认会自动配置证书续期任务,但也可以通过Python脚本手动触发续期操作,确保所有证书及时更新。以下是批量续期SSL证书的示例代码:
1 import subprocess
2 import csv
3
4 def renew_certificates():
5 with open('servers.csv', 'r') as csvfile:
6 reader = csv.DictReader(csvfile)
7 for row in reader:
8 domain = row['domain']
9 ip = row['ip']
10 username = row['username']
11 password = row['password']
12 web_server = row['web_server']
13 command = f"certbot renew --pre - hook'sudo service {web_server} stop' --post - hook'sudo service {web_server} start'"
14 try:
15 subprocess.run(command, shell=True, check=True)
16 print(f"Successfully renewed certificate for {domain}")
17 except subprocess.CalledProcessError as e:
18 print(f"Failed to renew certificate for {domain}: {e}")
19
20 if __name__ == "__main__":
21 renew_certificates()
上述代码中,通过 certbot renew 命令触发证书续期,在续期前后分别停止和启动Web服务器服务,确保续期过程顺利进行。
1. 账户安全:在使用ACME协议申请证书时,涉及的账户信息和API令牌等敏感数据需妥善保管,避免泄露。
2. 错误处理:在编写Python脚本过程中,要完善错误处理机制,如捕获 subprocess.CalledProcessError 、 paramiko.SSHException 等异常,及时打印错误信息,方便排查问题。
3. 备份重要文件:在修改Web服务器配置文件前,务必进行备份,以防配置错误导致服务无法正常运行。
4. DNS记录生效时间:使用DNS - 01挑战方式时,DNS记录的生效时间因DNS服务商而异,需合理设置等待时间,确保证书申请成功。
通过本教程,你已掌握使用Python脚本批量配置SSL证书的方法,从申请、安装到续期实现全流程自动化。在实际应用中,可根据具体需求对脚本进行调整和优化,若在操作中有任何疑问,欢迎随时交流。
Dogssl.com拥有20年网络安全服务经验,提供构涵盖国际CA机构Sectigo、Digicert、GeoTrust、GlobalSign,以及国内CA机构CFCA、沃通、vTrus、上海CA等数十个SSL证书品牌。全程技术支持及免费部署服务,如您有SSL证书需求,欢迎联系!