Skip to content
Threats Guide

ssl_tls_config.py

SSL/TLS Secure Configuration This script demonstrates secure SSL/TLS configuration for various servers and provides examples of proper encryption implementation.

  • prevention
  • python
  • 434 lines

Run security tools only on systems you own or have written permission to test.

Run it

From the repository root, after pip install -r tools/requirements.txt
cd 01-network-security/man-in-the-middle/prevention
python3 ssl_tls_config.py --help

Source

View on GitHub
#!/usr/bin/env python3"""SSL/TLS Secure ConfigurationThis script demonstrates secure SSL/TLS configuration for various serversand provides examples of proper encryption implementation.""" import sslimport socketimport hashlibimport hmacimport osfrom cryptography import x509from cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import hashes, serializationfrom cryptography.hazmat.primitives.asymmetric import rsafrom cryptography.x509.oid import NameOIDimport datetimeimport argparse class SecureTLSConfig:    """    Secure SSL/TLS Configuration Examples    """        def __init__(self):        self.secure_ciphers = [            'TLS_AES_256_GCM_SHA384',      # TLS 1.3            'TLS_CHACHA20_POLY1305_SHA256', # TLS 1.3            'TLS_AES_128_GCM_SHA256',      # TLS 1.3            'ECDHE-RSA-AES256-GCM-SHA384',  # TLS 1.2            'ECDHE-ECDSA-AES256-GCM-SHA384',# TLS 1.2        ]                self.weak_ciphers = [            'RC4',            'DES',            '3DES',            'MD5',            'EXPORT',            'NULL',            'anon',        ]            # ==================== SERVER CONFIGURATIONS ====================        def nginx_secure_config(self):        """Generate secure Nginx SSL configuration"""        config = """# /etc/nginx/nginx.conf or /etc/nginx/sites-available/example.comserver {    listen 443 ssl http2;    listen [::]:443 ssl http2;    server_name example.com;    # SSL Certificate paths    ssl_certificate /etc/ssl/certs/example.com.crt;    ssl_certificate_key /etc/ssl/private/example.com.key;    # Modern SSL/TLS configuration    ssl_protocols TLSv1.2 TLSv1.3;    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';    ssl_prefer_server_ciphers on;    # DH parameters (generate with: openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048)    ssl_dhparam /etc/ssl/certs/dhparam.pem;    # OCSP Stapling    ssl_stapling on;    ssl_stapling_verify on;    ssl_trusted_certificate /etc/ssl/certs/example.com.chain.crt;    # Security headers    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;    add_header X-Frame-Options DENY;    add_header X-Content-Type-Options nosniff;    add_header X-XSS-Protection "1; mode=block";    # Session settings    ssl_session_cache shared:SSL:50m;    ssl_session_timeout 1d;    ssl_session_tickets off;    # Root directory and other configurations    root /var/www/html;    index index.html index.htm;}"""        return config        def apache_secure_config(self):        """Generate secure Apache SSL configuration"""        config = """# /etc/apache2/sites-available/example.com-ssl.conf<VirtualHost *:443>    ServerName example.com    DocumentRoot /var/www/html    # SSL Engine    SSLEngine on    SSLCertificateFile /etc/ssl/certs/example.com.crt    SSLCertificateKeyFile /etc/ssl/private/example.com.key    SSLCertificateChainFile /etc/ssl/certs/example.com.chain.crt    # Protocol and Cipher configuration    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256    SSLHonorCipherOrder on    # DH parameters    SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"    # OCSP Stapling    SSLUseStapling on    SSLStaplingResponderTimeout 5    SSLStaplingReturnResponderErrors off    SSLStaplingCache "shmcb:logs/stapling-cache(150000)"    # Security headers    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"    Header always set X-Frame-Options DENY    Header always set X-Content-Type-Options nosniff    # Session cache    SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000)    SSLSessionCacheTimeout 300</VirtualHost>"""        return config        def iis_secure_config(self):        """Generate secure IIS SSL configuration (PowerShell)"""        config = r"""# PowerShell script for IIS SSL configuration# Import IIS moduleImport-Module WebAdministration# Set site name$siteName = "Default Web Site"# Disable weak protocolsNew-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" `    -Name "Enabled" -Value 0 -PropertyType "DWord" -ForceNew-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" `    -Name "Enabled" -Value 0 -PropertyType "DWord" -Force# Enable TLS 1.2 and 1.3New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" `    -Name "Enabled" -Value 1 -PropertyType "DWord" -ForceNew-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" `    -Name "DisabledByDefault" -Value 0 -PropertyType "DWord" -Force# Set cipher suite order (PowerShell 5.0+)$cipherSuites = @(    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256")$cipherSuitesString = [string]::Join(",", $cipherSuites)Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002" `    -Name "Functions" -Value $cipherSuitesString# Enable HSTS for the siteSet-WebConfigurationProperty -Filter "system.webServer/httpProtocol/customHeaders" `    -Name "." -Value @{name="Strict-Transport-Security";value="max-age=63072000; includeSubDomains; preload"} `    -PSPath "IIS:\Sites\$siteName"# Restart IISiisreset"""        return config        # ==================== PYTHON SSL EXAMPLES ====================        def create_ssl_context_server(self):        """Create secure SSL context for Python server"""        context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)                # Load certificate and key        context.load_cert_chain(certfile="server.crt", keyfile="server.key")                # Set minimum TLS version        context.minimum_version = ssl.TLSVersion.TLSv1_2                # Set secure ciphers        context.set_ciphers(':'.join(self.secure_ciphers))                # Enable perfect forward secrecy        context.set_ecdh_curve('prime256v1')                # Disable session tickets (less secure)        context.options |= ssl.OP_NO_TICKET                # Enable OCSP stapling (if available)        context.options |= ssl.OP_NO_COMPRESSION                return context        def create_ssl_context_client(self):        """Create secure SSL context for Python client"""        context = ssl.create_default_context()                # Require server certificate verification        context.check_hostname = True        context.verify_mode = ssl.CERT_REQUIRED                # Set minimum TLS version        context.minimum_version = ssl.TLSVersion.TLSv1_2                # Load system certificates (default)        context.load_default_certs()                return context        def secure_http_server(self):        """Example of secure HTTPS server"""        context = self.create_ssl_context_server()                # Create socket        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)        server_socket.bind(('0.0.0.0', 443))        server_socket.listen(5)                # Wrap socket with SSL        secure_socket = context.wrap_socket(server_socket, server_side=True)                print(f"{Fore.GREEN}[✓] Secure HTTPS server listening on port 443{Style.RESET_ALL}")        return secure_socket        def secure_http_client(self, hostname, port=443):        """Example of secure HTTPS client"""        context = self.create_ssl_context_client()                # Create socket and wrap with SSL        with socket.create_connection((hostname, port)) as sock:            with context.wrap_socket(sock, server_hostname=hostname) as ssock:                # Get certificate info                cert = ssock.getpeercert()                                print(f"{Fore.GREEN}[✓] Connected securely to {hostname}{Style.RESET_ALL}")                print(f"   Cipher: {ssock.cipher()}")                print(f"   Protocol: {ssock.version()}")                                # Send HTTPS request                request = f"GET / HTTP/1.1\r\nHost: {hostname}\r\nConnection: close\r\n\r\n"                ssock.send(request.encode())                                # Receive response                response = ssock.recv(4096)                return response        # ==================== CERTIFICATE GENERATION ====================        def generate_self_signed_cert(self, cert_file="server.crt", key_file="server.key", days=365):        """        Generate self-signed certificate (for development only!)        """        # Generate private key        private_key = rsa.generate_private_key(            public_exponent=65537,            key_size=2048,            backend=default_backend()        )                # Create certificate subject        subject = issuer = x509.Name([            x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),            x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"),            x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Example Org"),            x509.NameAttribute(NameOID.COMMON_NAME, "example.com"),        ])                # Build certificate        cert = x509.CertificateBuilder().subject_name(            subject        ).issuer_name(            issuer        ).public_key(            private_key.public_key()        ).serial_number(            x509.random_serial_number()        ).not_valid_before(            datetime.datetime.utcnow()        ).not_valid_after(            datetime.datetime.utcnow() + datetime.timedelta(days=days)        ).add_extension(            x509.SubjectAlternativeName([                x509.DNSName("localhost"),                x509.DNSName("example.com"),                x509.DNSName("*.example.com"),            ]),            critical=False,        ).sign(private_key, hashes.SHA256(), default_backend())                # Write private key        with open(key_file, "wb") as f:            f.write(private_key.private_bytes(                encoding=serialization.Encoding.PEM,                format=serialization.PrivateFormat.PKCS8,                encryption_algorithm=serialization.NoEncryption()            ))                # Write certificate        with open(cert_file, "wb") as f:            f.write(cert.public_bytes(serialization.Encoding.PEM))                print(f"{Fore.GREEN}[✓] Generated certificate: {cert_file}{Style.RESET_ALL}")        print(f"{Fore.GREEN}[✓] Generated key: {key_file}{Style.RESET_ALL}")        print(f"{Fore.YELLOW}[!] For production, use certificates from trusted CA{Style.RESET_ALL}")        # ==================== SECURITY CHECKS ====================        def check_server_ssl(self, hostname, port=443):        """Check SSL/TLS configuration of a server"""        print(f"\n{Fore.CYAN}[*] Checking SSL/TLS configuration for {hostname}:{port}{Style.RESET_ALL}")                try:            context = ssl.create_default_context()            with socket.create_connection((hostname, port), timeout=5) as sock:                with context.wrap_socket(sock, server_hostname=hostname) as ssock:                                        # Get certificate                    cert = ssock.getpeercert()                                        # Check protocol version                    protocol = ssock.version()                    print(f"   Protocol: {protocol}")                                        # Check cipher                    cipher = ssock.cipher()                    print(f"   Cipher: {cipher[0]}")                                        # Check certificate expiration                    from datetime import datetime                    not_after = cert['notAfter']                    expiry = datetime.strptime(not_after, '%b %d %H:%M:%S %Y %Z')                    days_left = (expiry - datetime.now()).days                                        if days_left < 30:                        print(f"{Fore.RED}   [!] Certificate expires in {days_left} days{Style.RESET_ALL}")                    else:                        print(f"{Fore.GREEN}   [✓] Certificate valid for {days_left} days{Style.RESET_ALL}")                                        # Check for weak protocol                    if protocol in ['TLSv1', 'TLSv1.1']:                        print(f"{Fore.RED}   [!] Weak protocol detected: {protocol}{Style.RESET_ALL}")                                        # Check for weak cipher                    for weak in self.weak_ciphers:                        if weak in cipher[0]:                            print(f"{Fore.RED}   [!] Weak cipher detected: {cipher[0]}{Style.RESET_ALL}")                                        return True                            except Exception as e:            print(f"{Fore.RED}[!] Error checking SSL: {e}{Style.RESET_ALL}")            return False        def generate_hsts_header(self, max_age=63072000, include_subdomains=True, preload=True):        """Generate HSTS header value"""        header = f"max-age={max_age}"        if include_subdomains:            header += "; includeSubDomains"        if preload:            header += "; preload"        return header def demonstrate_configs():    """Demonstrate SSL/TLS configurations"""    config = SecureTLSConfig()        print(f"""    {Fore.CYAN}╔═══════════════════════════════════════╗    ║     SSL/TLS Secure Configuration     ║    ║       MITM Prevention Examples       ║    ╚═══════════════════════════════════════╝{Style.RESET_ALL}    """)        # 1. Nginx Configuration    print(f"\n{Fore.GREEN}1. Nginx SSL Configuration:{Style.RESET_ALL}")    print(config.nginx_secure_config())        # 2. Apache Configuration    print(f"\n{Fore.GREEN}2. Apache SSL Configuration:{Style.RESET_ALL}")    print(config.apache_secure_config())        # 3. HSTS Header    print(f"\n{Fore.GREEN}3. HSTS Header:{Style.RESET_ALL}")    print(f"   {config.generate_hsts_header()}")        # 4. Check a server    print(f"\n{Fore.GREEN}4. Checking example.com SSL:{Style.RESET_ALL}")    config.check_server_ssl("example.com")        # 5. Generate test certificate (optional)    print(f"\n{Fore.GREEN}5. Generate development certificate:{Style.RESET_ALL}")    print("   Use: python3 ssl_tls_config.py --generate-cert") def main():    parser = argparse.ArgumentParser(description='SSL/TLS Secure Configuration')    parser.add_argument('--generate-cert', action='store_true',                        help='Generate self-signed certificate for testing')    parser.add_argument('--check', metavar='HOSTNAME',                        help='Check SSL configuration of a server')    parser.add_argument('--demo', action='store_true',                        help='Run demonstration')        args = parser.parse_args()        config = SecureTLSConfig()        if args.generate_cert:        config.generate_self_signed_cert()        elif args.check:        config.check_server_ssl(args.check)        elif args.demo:        demonstrate_configs()        else:        print("Use --demo for examples or --help for options") if __name__ == "__main__":    from colorama import init, Fore, Style    init(autoreset=True)    main()