杰瑞科技汇

Ubuntu下Python如何配置SSL?

Of course! The combination of "Python," "SSL," and "Ubuntu" is very common. This guide will cover the essential aspects, from setting up your Ubuntu environment to writing Python code to handle SSL/TLS securely.

Ubuntu下Python如何配置SSL?-图1
(图片来源网络,侵删)

We'll break this down into three main parts:

  1. System-Level Setup on Ubuntu: Ensuring OpenSSL and necessary certificates are in place.
  2. Python-Level Setup: Using the built-in ssl module.
  3. Practical Code Examples: Creating both SSL clients and servers.

Part 1: System-Level Setup on Ubuntu

Before your Python code can use SSL, your Ubuntu system needs the underlying libraries and certificates.

Install OpenSSL

Python's ssl module is a wrapper around the OpenSSL library. It's almost always pre-installed, but you can ensure it's there and get development headers if needed.

# Update your package list
sudo apt update
# Install OpenSSL and its development libraries
sudo apt install openssl libssl-dev

Get SSL Certificates

SSL/TLS requires certificates to verify the identity of servers and (optionally) clients. There are two common scenarios:

Ubuntu下Python如何配置SSL?-图2
(图片来源网络,侵删)

Scenario A: Development and Testing (Self-Signed Certificates) For local development, you can create your own self-signed certificate. Browsers will show a security warning, which is expected and fine for testing.

  1. Generate a Private Key:

    openssl genrsa -out server.key 2048
  2. Create a Certificate Signing Request (CSR):

    openssl req -new -key server.key -out server.csr

    You'll be prompted for information. For a local server, you can fill in dummy data. The most important field is the Common Name (CN). For a server running on your local machine, use localhost.

    Ubuntu下Python如何配置SSL?-图3
    (图片来源网络,侵删)
  3. Generate the Self-Signed Certificate:

    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

    This creates a valid certificate for one year.

Scenario B: Production (Certificates from a Trusted CA) For public-facing applications, you need certificates issued by a trusted Certificate Authority (CA) like Let's Encrypt (free), DigiCert, or Sectigo. The most common tool to get these is certbot.

# Install Certbot
sudo apt install certbot
# Example: Get a certificate for a domain (e.g., yourdomain.com)
# This will attempt to automatically configure Nginx or Apache for you.
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will place your certificates in /etc/letsencrypt/live/yourdomain.com/. The private key is privkey.pem and the full certificate chain is fullchain.pem.


Part 2: The Python ssl Module

Python's standard library has a powerful ssl module. You don't need to install it with pip.

Key concepts:

  • ssl.create_default_context(): This is the recommended way to create an SSL context. It provides a secure default configuration, including:
    • Verifying server certificates.
    • Not allowing insecure protocols (like SSLv2, SSLv3).
    • Using strong, modern cipher suites.
  • ssl.SSLContext: A more advanced way to create contexts if you need fine-grained control (e.g., creating your own client certificate, loading a specific CA bundle).
  • ssl.wrap_socket(): Wraps an existing socket (e.g., one created with socket.socket()) to enable SSL/TLS.

Part 3: Practical Code Examples

Let's put it all together. We'll create a simple chat application: an SSL server and an SSL client.

File Structure

.
├── server.py
├── client.py
└── certs/
    ├── server.crt
    └── server.key

Step 1: Create the SSL Server (server.py)

This server will listen for connections, accept them, and then communicate over a secure channel.

# server.py
import socket
import ssl
import sys
HOST = '0.0.0.0'  # Listen on all available interfaces
PORT = 8443
# Path to the certificate and key files
# Make sure these paths are correct!
CERTFILE = 'certs/server.crt'
KEYFILE = 'certs/server.key'
def start_server():
    # Create a TCP socket
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile=CERTFILE, keyfile=KEYFILE)
    # Create the underlying server socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.bind((HOST, PORT))
        sock.listen(5)
        print(f"Server listening on {HOST}:{PORT}")
        while True:
            # Accept a new connection
            conn, addr = sock.accept()
            # Wrap the socket with SSL
            with context.wrap_socket(conn, server_side=True) as ssock:
                print(f"Secure connection established with {addr}")
                try:
                    # Receive data from the client
                    data = ssock.recv(1024)
                    if not data:
                        break
                    print(f"Received from client: {data.decode('utf-8')}")
                    # Send a response back
                    response = "Hello from the secure server!"
                    ssock.sendall(response.encode('utf-8'))
                except ssl.SSLError as e:
                    print(f"SSL Error: {e}")
                finally:
                    print(f"Closing connection with {addr}")
                    ssock.close()
if __name__ == "__main__":
    start_server()

Step 2: Create the SSL Client (client.py)

This client will connect to the server and send a message.

# client.py
import socket
import ssl
import sys
HOST = '127.0.0.1'  # Use 'localhost' or the server's IP address
PORT = 8443
# Path to the server's certificate for verification
# This tells the client to trust this specific certificate.
# For production, you'd use a CA bundle (e.g., /etc/ssl/certs/ca-certificates.crt).
CERTFILE = 'certs/server.crt'
def start_client():
    # Create a default SSL context
    context = ssl.create_default_context()
    # Load the CA certificate to verify the server's identity
    context.load_verify_locations(CERTFILE)
    # Create the underlying TCP socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        # Wrap the socket with SSL
        with context.wrap_socket(sock, server_hostname=HOST) as ssock:
            print(f"Connecting to {HOST}:{PORT}...")
            ssock.connect((HOST, PORT))
            # Send data to the server
            message = "Hello from the secure client!"
            ssock.sendall(message.encode('utf-8'))
            print(f"Sent to server: {message}")
            # Receive a response
            response = ssock.recv(1024)
            print(f"Received from server: {response.decode('utf-8')}")
if __name__ == "__main__":
    start_client()

Step 3: Run the Application on Ubuntu

  1. Create the certs directory and generate the self-signed certificates as described in Part 1.

    mkdir certs
    openssl genrsa -out certs/server.key 2048
    openssl req -new -key certs/server.key -out certs/server.csr
    openssl x509 -req -days 365 -in certs/server.csr -signkey certs/server.key -out certs/server.crt
    # You can now delete the .csr file
    rm certs/server.csr
  2. Run the server in one terminal:

    python3 server.py

    You should see: Server listening on 0.0.0.0:8443

  3. Run the client in a second terminal:

    python3 client.py

You will see the messages being sent and received, all encrypted by SSL/TLS.


Common Issues and Solutions

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] ... self signed certificate

  • Cause: This is the most common error. It happens when the client (or server) is trying to verify a certificate but doesn't trust it. This is expected with self-signed certificates.
  • Solution (for client-side):
    • For Development: You can tell the client to not verify the certificate. This is insecure and should only be used for testing!
      # In client.py, modify the context creation
      context = ssl._create_unverified_context() # DANGEROUS!
    • The Correct Way: Provide the client with the server's public certificate (.crt file) so it knows who to trust. Our example code already does this correctly with context.load_verify_locations(CERTFILE).

ConnectionRefusedError or [Errno 111] Connection refused

  • Cause: The server is not running, or it's running on a different port than the one the client is trying to connect to.
  • Solution: Double-check that server.py is running and that the HOST and PORT variables in client.py match the server's address and port.

OSError: [Errno 98] Address already in use

  • Cause: You tried to start the server, but another program is already using the specified PORT.
  • Solution: Change the PORT variable in server.py to a different number (e.g., 8444) or find and kill the process using the port.
    # Find the process
    sudo lsof -i :8443
    # Kill the process (replace PID with the actual number)
    sudo kill -9 <PID>
分享:
扫描分享到社交APP
上一篇
下一篇