当前位置: 首页 > news >正文

C#更新Nginx SSL证书

现在免费的SSL证书三个月就到期了,为了方便写了一个更新SSL证书的程序,把程序和xxx_nginx.zip的证书放在同一目录下,先解压ssl文件,然后上传到服务器,最后复制到nginx的路径下。一台服务器有多个ssl证书,最好ssl有效期控制在同一天这样方便更新,只需要将多个ssl压缩包和程序放在一起即可。

代码如下:

Install-Package DotNetZip -Version 1.16.0
Install-Package SSH.NET -Version 2024.2.0
using Ionic.Zip;
using Renci.SshNet;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        Console.WriteLine("即将启动SSL证书更新,按任意键继续。");
        Console.ReadKey();
        string currentDir = Directory.GetCurrentDirectory();
       var result = UnzipFile(currentDir);
        if (!result)
        {
            Console.WriteLine("文件提取失败");
            Console.WriteLine("按任意键退出");
            Console.ReadKey();
            return;
        }
        Console.WriteLine("文件提取完成");
        Console.WriteLine("按任意键继续");
        Console.ReadKey();
        SSHClient(currentDir);
        Console.WriteLine("按任意键退出任务");
        Console.ReadKey();
    }

    public static bool UnzipFile(string currentDir)
    {
        var files = Directory.GetFiles(currentDir, "*nginx.zip");
        if (files.Length == 0)
        {
            return false;
        }
        foreach (string zipFile in files)
        {
            try
            {
                using (ZipFile zip = ZipFile.Read(zipFile, new ReadOptions { Encoding = System.Text.Encoding.Default }))
                {
                    foreach (ZipEntry entry in zip)
                    {
                        if (entry.IsDirectory) continue;
                        string ext = Path.GetExtension(entry.FileName).ToLower();
                        if (ext == ".key" || ext == ".pem")//根据自己要求,也可以把所有文件都解压出啦
                        {
                            entry.Extract(currentDir, ExtractExistingFileAction.OverwriteSilently);
                        }
                    }
                }
                var path = Path.Combine(currentDir, Path.GetFileNameWithoutExtension(zipFile));
                foreach (string file in Directory.GetFiles(path))
                {
                    string destFile = Path.Combine(currentDir, Path.GetFileName(file));
                    File.Copy(file, destFile, true);  // true表示如果文件已存在则覆盖
                }
                Directory.Delete(path, true);

            }
            catch (Exception ex)
            {
                Console.WriteLine($"解压失败:{zipFile}\n错误信息:{ex.Message}");
                return false;
            }
        }
        return true;
    }
    public static void SSHClient(string currentDir)
    {
        
        string host = "host";  // 服务器地址
        string username = "username";  // 登录用户名
        string password = "password";  // 登录密码
        string remoteFilePath = "/home/username/ssl/";  // 远程服务器上的目标文件路径
        string sudoPassword = "sudoPassword";  // sudo 密码

        try
        {
            // 上传文件到服务器
            using (var sftp = new SftpClient(host, username, password))
            {
                sftp.Connect();
                Console.WriteLine("成功连接到FTP服务器");

                var allFiles = Directory.GetFiles(currentDir)//根据自己要求过滤文件
                                 .Where(file => file.EndsWith(".key", StringComparison.OrdinalIgnoreCase) ||
                                                file.EndsWith(".pem", StringComparison.OrdinalIgnoreCase));

                foreach (var item in allFiles)
                {
                    using (var fileStream = File.OpenRead(item))
                    {
                        sftp.UploadFile(fileStream, $"{remoteFilePath + Path.GetFileName(item)}");
                        Console.WriteLine($"{Path.GetFileName(item)}文件上传成功!");
                    }
                } 

                sftp.Disconnect();
                Console.WriteLine("FTP服务器断开连接");
                Console.WriteLine("按任意键继续");
                Console.ReadKey();
            }

            // 执行sudo命令
            using (var sshClient = new SshClient(host, username, password))
            {
                sshClient.Connect();
                Console.WriteLine("成功连接到SSH服务器");

                // 通过 SSH 执行需要 sudo 的命令
                string sudoCommand = "echo " + sudoPassword + " | sudo -S /home/username/update_ssl.sh"; // 这里用 echo 将密码传递给 sudo
                
                var command = sshClient.RunCommand(sudoCommand);
                if (!string.IsNullOrEmpty(command.Error))
                {
                    Console.WriteLine("命令执行消息:"+command.Error);
                }
                Console.WriteLine("命令执行结果: " + command.Result);

                sshClient.Disconnect();
                Console.WriteLine("SSH服务器断开连接");
                
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("错误: " + ex.Message);
        }
    }
}

update_ssl.sh 代码如下

#!/bin/bash
# 复制证书文件(需root权限)
sudo cp /home/username/ssl/* /etc/nginx/conf.d/ssl/

# 检查配置语法并重载
if sudo nginx -t; then
    sudo nginx -s reload
    echo "SSL证书更新成功!"
else
    echo "Nginx配置检查失败,请排查错误!"
    exit 1
fi

配置免密sudo‌

echo sudoPassword | sudo -S ./update_ssl.sh #替代安全方案‌
#在/etc/sudoers中添加NOPASSWD规则,允许特定命令无需密码:
username ALL=(ALL) NOPASSWD: /home/username/update_ssl.sh

相关文章:

  • nestjs 多环境配置
  • git 操作:撤销Merge
  • NOIP 2024 解题分析
  • nginx之gzip_static详解
  • Matplotlib查看 rc 参数的方法
  • JNI 本地方法调用 Java 静态方法 和 实例方法对比;通过本地方法创建 Java 对象;本地方法访问 Java 数组元素;本地方法错误返回给 Java
  • Linux Shell 基础操作笔记
  • charles接口测试(断点测试)
  • 本人设计的最完全的光压发电机模型
  • 05_循环结构三目运算符
  • Spring MVC 配置详解与入门案例
  • SpringBoot 面试八股文
  • 基于@Scheduled注解(静态配置)实现定时任务
  • SQL调优
  • 搭建PG库和安装pgvector、pgRouting插件
  • uniapp 微信小程序图片下载保存功能
  • TypeScript 泛型 < T > 从入门到精通
  • 可视化图解算法:删除有序(排序)链表中重复的元素
  • 基于AOP注解+Redisson实现Cache-Aside缓存模式实战
  • 春日焕新居:约克VRF中央空调,科技赋能,带你开启健康呼吸新时代
  • 中国建设银行原党委委员、副行长章更生被决定逮捕
  • 中方对美俄领导人就俄乌冲突进行通话有何评论?外交部回应
  • 特朗普与泽连斯基通话
  • 北美票房|华纳又赢了,《死神来了6》开画远超预期
  • 从《缶翁的世界》看吴昌硕等湖州籍书画家对海派的影响
  • 家国万里·时光故事会|构筑中国船舰钢筋铁骨,她在焊花里展现工匠风范