Email:Service@dogssl.com
CNY
Python脚本批量配置SSL证书教程
更新时间:2025-07-02 作者:批量配置SSL证书

借助Python脚本实现批量配置SSL证书,能够显著提升效率,减少人为错误。本教程将详细介绍如何使用Python脚本完成SSL证书的批量申请、安装与续期。

一、前期准备工作

1. 了解SSL证书与ACME协议

在开始编写Python脚本前,需对SSL证书和ACME协议有基本了解。SSL证书用于在客户端和服务器之间建立加密连接,确保数据传输安全;ACME协议则是一种用于自动化管理SSL证书的开放标准协议,支持客户端与证书颁发机构(CA)进行交互,实现证书的申请、验证、颁发和续期等操作。目前,Let's Encrypt是使用ACME协议的知名免费CA,其提供的证书适用于大多数场景,我们的教程也将以Let's Encrypt为例进行讲解。

2. 安装必要的Python库

实现批量配置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

3. 准备域名列表与服务器信息

准备一个包含所有待配置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

二、使用Python脚本批量申请SSL证书

1. 基于HTTP - 01挑战的证书申请

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 替换为实际的邮箱地址,该邮箱用于接收证书相关通知。

2. 基于DNS - 01挑战的证书申请

当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 替换为真实邮箱地址。

三、使用Python脚本批量安装SSL证书

证书申请成功后,需要将证书安装到对应的Web服务器上。以下以Nginx和Apache为例,介绍如何使用Python脚本实现批量安装。

1. 在Nginx服务器上批量安装证书

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服务,完成证书安装。

2. 在Apache服务器上批量安装证书

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服务,实现证书安装。

四、使用Python脚本批量续期SSL证书

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机构SectigoDigicertGeoTrustGlobalSign,以及国内CA机构CFCA沃通vTrus上海CA等数十个SSL证书品牌。全程技术支持及免费部署服务,如您有SSL证书需求,欢迎联系!
相关文档
立即加入,让您的品牌更加安全可靠!
申请SSL证书
0.099060s