diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 7b4a29f..5d31460 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -4,7 +4,7 @@ on: [push] jobs: Build Docker: - runs-on: ubuntu-latest + runs-on: [ubuntu-latest, arm] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/bot.py b/bot.py index ce9d064..761692e 100644 --- a/bot.py +++ b/bot.py @@ -5,6 +5,8 @@ from discord import app_commands import requests import dns.resolver import markdownify +import subprocess +import tempfile load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') @@ -124,6 +126,92 @@ async def curl(ctx, url: str): await ctx.response.send_message(f"An error occurred: {e}") except Exception as e: await ctx.response.send_message(f"An error occurred: {e}") + +@tree.command(name="ssl", description="Check SSL certificate") +async def ssl(ctx, domain: str): + + + message = "" + resolver = dns.resolver.Resolver() + resolver.nameservers = ["100.74.29.146"] + resolver.port = 53 + try: + # Query the DNS record + response = resolver.resolve(domain, "A") + records = [] + message = "## A records:\n" + for record in response: + records.append(str(record)) + message = message + "- " +str(record) + "\n" + + + if records.count < 1: + await ctx.response.send_message(f"No A record found for {domain}") + return + + # Get the first A record + ip = records[0] + + # Run the openssl s_client command + s_client_command = ["openssl","s_client","-showcerts","-connect",f"{ip}:443","-servername",domain,"<","/dev/null",] + + s_client_process = subprocess.Popen(s_client_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + s_client_output, _ = s_client_process.communicate() + + certificates = [] + current_cert = "" + for line in s_client_output.split(b"\n"): + current_cert += line.decode("utf-8") + "\n" + if "-----END CERTIFICATE-----" in line.decode("utf-8"): + certificates.append(current_cert) + current_cert = "" + + if certificates: + cert = certificates[0] + message = message + "\n## Website Certificate:\n`" + cert + "`\n" + + with tempfile.NamedTemporaryFile(mode="w", delete=False) as temp_cert_file: + temp_cert_file.write(cert) + temp_cert_file.seek(0) # Move back to the beginning of the temporary file + + tlsa_command = [ + "openssl", + "x509", + "-in", + temp_cert_file.name, + "-pubkey", + "-noout", + "|", + "openssl", + "pkey", + "-pubin", + "-outform", + "der", + "|", + "openssl", + "dgst", + "-sha256", + "-binary", + "|", + "xxd", + "-p", + "-u", + "-c", + "32", + ] + tlsa_process = subprocess.Popen(" ".join(tlsa_command), shell=True, stdout=subprocess.PIPE) + tlsa_output, _ = tlsa_process.communicate() + + message = message + "\n## TLSA Record from webserver: `3 1 1 " + tlsa_output.decode("utf-8") + "`\n" + await ctx.response.send_message(message) + else: + ctx.response.send_message(f"No certificate found for {domain}") + return + + # Catch all exceptions + except Exception as e: + await ctx.response.send_message(f"An error occurred: {e}") + @tree.command(name="invite", description="Invite me to your server") async def invite(ctx):