Skip to content

Conversation

@fokx
Copy link

@fokx fokx commented Jul 25, 2025

add config option: hostname, auto_ssl
for auto_ssl, if enabled, will ignore self_sign. if failed, will fallback to self-sign if both certificate and private_key are set, will be the path to save certificate and key on startup, if this option is a valid domain name, will try to use instant-acme crate to issue a cert for it, using letsencrypt CA, then save the cert and key to private_key and certificate specified in config, if not configured, save to the same directory of config file. If acme failed, will leave a warning in log and self sign a cert (generate_simple_self_signed). If acme success, then spawn a process to check if cert is valid every 12 hour and if it is about to expire in 3 days, renew it

P.S. Feel free to modify

add config option: hostname, auto_ssl
for auto_ssl, if enabled, will ignore `self_sign`. if failed, will fallback to self-sign
if both certificate and private_key are set, will be the path to save certificate and key
on startup, if this option is a valid domain name, will try to use `instant-acme` crate to issue a cert for it, using letsencrypt CA, then save the cert and key to private_key and certificate specified in config, if not configured, save to the same directory of config file. If acme failed, will leave a warning in log and self sign a cert (generate_simple_self_signed). If acme success, then spawn a process to check if cert is valid every 12 hour and if it is about to expire in 3 days, renew it
@Itsusinn Itsusinn self-assigned this Jul 25, 2025
@fokx
Copy link
Author

fokx commented Jul 25, 2025

Thanks for beginning to work on this, I think it's better to replace my current is_certificate_expiring function in tuic-server/tls.rs with:

/// Check if a certificate is about to expire (within the specified days)
pub async fn is_certificate_expiring(cert_path: &Path, days_threshold: u64) -> Result<bool> {
    let cert_data = fs::read(cert_path)
        .await
        .context("Failed to read certificate file")?;

    // Parse the certificate using x509-parser
    let res = parse_x509_pem(&cert_data);
    match res {
        Ok((rem, pem)) => {
            if !rem.is_empty() {
                warn!("Extra data after certificate");
            }
            if pem.label != "CERTIFICATE" {
                warn!("Invalid PEM label: {:?}", pem.label);
            }
            let res_x509 = parse_x509_certificate(&pem.contents);
            match res_x509 {
                Ok((_, parsed_cert)) => {
                    // Get current time as seconds since Unix epoch
                    let now = SystemTime::now()
                        .duration_since(SystemTime::UNIX_EPOCH)
                        .context("Failed to get current time")?
                        .as_secs();

                    // Get certificate expiration time
                    let not_after = parsed_cert.tbs_certificate.validity.not_after.timestamp() as u64;

                    // Calculate threshold time (current time + days_threshold)
                    let threshold_time = now + (days_threshold * 24 * 60 * 60);

                    // Certificate is expiring if the expiration time is before our threshold
                    Ok(not_after <= threshold_time)
                }
                Err(e) => {
                    Err(eyre::eyre!("Failed to parse X.509 certificate: {:?}", e))
                }
            }
        }
        Err(e) => {
            Err(eyre::eyre!("Failed to parse PEM certificate: {:?}", e))
        }
    }
}

@Itsusinn Itsusinn requested a review from Copilot July 25, 2025 14:29

This comment was marked as outdated.

@Itsusinn
Copy link
Owner

Have you considered other certificate format?

@fokx
Copy link
Author

fokx commented Jul 27, 2025

You mean save the newly provisioned certificate as DER? I think it is enough to save it in PEM format.

@Itsusinn
Copy link
Owner

Itsusinn commented Jul 27, 2025

You mean save the newly provisioned certificate as DER? I think it is enough to save it in PEM format.

I mean all functions in tls.rs, they probably would be used in other place.

But i am also about to delete DER support completely.

@fokx
Copy link
Author

fokx commented Jul 27, 2025

As you are going to delete DER support, I think no further modifications are necessary.

@Itsusinn Itsusinn requested a review from Copilot July 27, 2025 11:05

This comment was marked as resolved.

@Itsusinn Itsusinn merged commit 532833c into Itsusinn:dev Aug 3, 2025
20 checks passed
@fokx fokx deleted the server-auto-ssl branch August 4, 2025 00:59
@Itsusinn
Copy link
Owner

Is it posssible to setup a ACME server for test-usage ? @fokx
I wanna know is there a crate can helps this case

@fokx
Copy link
Author

fokx commented Aug 26, 2025

Sorry, I found most acme crates focus on client side:
https://crates.io/keywords/acme
I failed to find one that can mimic a ACME server.

As for the auto-ssl feature, I've deployed tuic-server on several servers with various domains and confirm it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants