preface

Introduction of the certificate

Information security is more and more important, HTTPS has become quite popular, to make our HTTP interface support HTPPS, only need an SSL certificate

  • Public Key Certificate (PKC), which contains the basic information of the owner, the expiration time of the Certificate and the Public Key of the owner, and is digitally signed by the Certification Authority (CA), indicating that, A certification body determines that the public key really belongs to that person
  • Self-signed certificate, is that we act as a certification body, this certificate is recommended in the test development process, production environment directly on the CA certificate to save worry!

practice

Certificate generated

To prepare

  • Make sure you have the OpenSSL library

  • Create a directory

    # Root certificate directory
    [root@centos7 ~]# mkdir -p /var/ssl/crt/root
    # server certificate directory
    [root@centos7 ~]# mkdir -p /var/ssl/crt/server
    Copy the code

Generating a Root Certificate

  • Private key, symmetric RSA encryption, AES is more secure than DES, the key length is 2048 bytes

    openssl genrsa -aes256 -out /var/ssl/crt/root/ca.key -passout pass:"123456" 2048
    Copy the code
  • Request process, including certificate information, among which the key is CN, is to fill in your domain name, root certificate service can be written freely,

    openssl req -new -key /var/ssl/crt/root/ca.key -out /var/ssl/crt/root/ca.csr -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=www.ca.crt.com/[email protected]" -passin pass:"123456"
    Copy the code
  • Issue a certificate, this generates a usable certificate, note that without the v3_ca plugin, the browser cannot import

    openssl x509 -req -sha256 -extensions v3_ca -days 3650 -in /var/ssl/crt/root/ca.csr -out /var/ssl/crt/root/ca.crt -signkey /var/ssl/crt/root/ca.key -CAcreateserial -passin pass:"123456"
    Copy the code

Generate a server certificate

After the root certificate is obtained, all server certificates are checked out from the root certificate to facilitate unified access by clients

  • Private key, symmetric RSA encryption, AES is more secure than DES, the key length is 2048 bytes

    openssl genrsa -aes256 -out /var/ssl/crt/server/svc1-server.key -passout pass:"123456" 2048
    Copy the code
  • Request process, including certificate information, which is more critical CN, is to fill in your domain name

    openssl req -new -key /var/ssl/crt/server/svc1-server.key -out /var/ssl/crt/server/svc1-server.csr -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=www.svc1.com/[email protected]" -passin pass:"123456"
    Copy the code
  • Issue a certificate, this generates a usable certificate, note that without the v3_ca plugin, the browser cannot import

    openssl x509 -req -sha256 -extensions v3_req -days 3650 -in/var/ssl/crt/server/svc1-server.csr -out /var/ssl/crt/server/svc1-server.crt -signkey /var/ssl/crt/server/svc1-server.key -CAkey /var/ssl/crt/root/ca.key -CA /var/ssl/crt/root/ca.crt -CAcreateserial -passin  pass:"123456"
    Copy the code
  • Verification certificate

    openssl verify -CAfile /var/ssl/crt/root/ca.crt /var/ssl/crt/server/svc1-server.crt
    Copy the code

A certificate to use

Unubtu, for example

apt install nginx -y
Copy the code

configuration

vi /etc/nginx/sites-available/default

# Add the following at the end
server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  www.svc1.com;
    root         /usr/share/nginx/html;
    ssl_certificate "/var/ssl/crt/server/svc1-server.crt";
    ssl_certificate_key "/var/ssl/crt/server/svc1-server.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:! aNULL:! MD5; ssl_prefer_server_ciphers on; include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }Copy the code
Vi/etc/hosts 127.0.0.1 at www.svc1.comCopy the code

Start the

root@CN-00013965:/# sudo service nginx restart 
 * Restarting nginx nginx                                                                                                                                                           Enter PEM pass phrase:
Enter PEM pass phrase:                              [ OK ]
Copy the code

test

  • Certificate failure

    root@CN-00013965:/# wget https://www.svc1.com--2019-10-18 16:37:48-- https://www.svc1.com/ Resolving www.svc1.com (www.svc1.com)... 127.0.0.1 Connecting to www.svc1.com (www.svc1.com) | 127.0.0.1 | : 443... connected. ERROR: cannot verify www.svc1.com's certificate, Issued by [email protected], CN=www.ca.crt.com, OU = mygroup, O = myorganization, L = mycity, ST = myprovince, C = CN ': Unable to locally verify the issuer's authority.
    To connect to www.svc1.com insecurely, use `--no-check-certificate'.
    Copy the code
  • The access succeeded using the root certificate

    root@CN-00013965:/# wget --ca-certificate=/var/ssl/crt/root/ca.crt https://www.svc1.com--2019-10-18 16:39:50-- https://www.svc1.com/ Resolving www.svc1.com (www.svc1.com)... 127.0.0.1 Connecting to www.svc1.com (www.svc1.com) | 127.0.0.1 | : 443... connected. HTTP request sent, awaiting response... 200 OK Length: 612 [text/html] Saving to: 'index. HTML. 1' index. HTML. 1 100% [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = >] 612 --.-KB/sin 0s      
    
    2019-10-18 16:39:50 (32.4 MB/s) - ‘index.html.1’ saved [612/612]
    Copy the code

Importing a Java Application

Java applications need to read server certificates through the KEYSTORE file in PKCS12 format. We can distinguish different server certificates with aliases. Then we read the TrustKeystore to access HTTPS for other services

  • Generate the keystore

    openssl pkcs12 -export -clcerts -in /var/ssl/crt/server/svc1-server.crt -inkey /var/ssl/crt/server/svc1-server.key -out /var/ssl/crt/server/svc1-server.p12 -name svc1 -passin pass:"123456" -password pass:"123456"
    Copy the code

    The keytool command comes with JDK and is executed in ${JAVA_HOME}/bin. -srcstorePass is the password of the certificate and the other two are the passwords of the keystore

    keytool -importkeystore -trustcacerts -noprompt -deststoretype pkcs12 -srcstoretype pkcs12 -srckeystore /var/ssl/crt/server/svc1-server.p12 -destkeystore /var/ssl/crt/server/svc1-server.keystore -alias svc1 -deststorepass "123456" -destkeypass "123456" -srcstorepass "123456"
    Copy the code
  • Generate trustkeystore

    keytool -import -trustcacerts -noprompt -alias CA -file /var/ssl/crt/root/ca.crt -keystore /var/ssl/crt/root/ca.trustkeystore -storepass "123456"
    Copy the code

monitoring

If the certificate is displayed on the service port, how can we view the certificate information or check the certificate expiration information in real time? For example, port 443 has been default

root@CN-00013965:/5 # echo 'Q' | timeout openssl s_client - connect 127.0.0.1:443 2 > / dev/null | openssl x509 - noout - subject - dates

subject=C = CN, ST = myprovince, L = mycity, O = myorganization, OU = mygroup, CN = www.svc1.com, emailAddress = [email protected]
notBefore=Oct 18 08:09:32 2019 GMT
notAfter=Oct 15 08:09:32 2029 GMT
Copy the code

If you are using HTTPS from a PostgresQL database, openSSL cannot directly obtain the port certificate. You can use python script, which is found on Github

#! /usr/bin/env python

import argparse
import socket
import ssl
import struct
import subprocess
import sys

try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse


def main() :
    args = get_args()
    target = get_target_address_from_args(args)
    sock = socket.create_connection(target)
    try:
        certificate_as_pem = get_certificate_from_socket(sock)
        print(certificate_as_pem.decode('utf-8'))
    except Exception as exc:
        sys.stderr.write('Something failed while fetching certificate: {0}\n'.format(exc))
        sys.exit(1)
    finally:
        sock.close()


def get_args() :
    parser = argparse.ArgumentParser()
    parser.add_argument('database'.help='Either an IP address, hostname or URL with host and port')
    return parser.parse_args()


def get_target_address_from_args(args) :
    specified_target = args.database
    if '/ /' not in specified_target:
        specified_target = '/ /' + specified_target
    parsed = urlparse(specified_target)
    return (parsed.hostname, parsed.port or 5432)


def get_certificate_from_socket(sock) :
    request_ssl(sock)
    ssl_context = get_ssl_context()
    sock = ssl_context.wrap_socket(sock)
    sock.do_handshake()
    certificate_as_der = sock.getpeercert(binary_form=True)
    certificate_as_pem = encode_der_as_pem(certificate_as_der)
    return certificate_as_pem


def request_ssl(sock) :
    version_ssl = postgres_protocol_version_to_binary(1234.5679)
    length = struct.pack('! I'.8)
    packet = length + version_ssl

    sock.sendall(packet)
    data = read_n_bytes_from_socket(sock, 1)
    ifdata ! =b'S':
        raise Exception('Backend does not support TLS')


def get_ssl_context() :
    for proto in ('PROTOCOL_TLSv1_2'.'PROTOCOL_TLSv1'.'PROTOCOL_SSLv23'):
        protocol = getattr(ssl, proto, None)
        if protocol:
            break
    return ssl.SSLContext(protocol)


def encode_der_as_pem(cert) :
    cmd = ['openssl'.'x509'.'-inform'.'DER']
    pipe = subprocess.PIPE
    process = subprocess.Popen(cmd, stdin=pipe, stdout=pipe, stderr=pipe)
    stdout, stderr = process.communicate(cert)
    if stderr:
        raise Exception('OpenSSL error when converting cert to PEM: {0}'.format(stderr))
    return stdout.strip()


def read_n_bytes_from_socket(sock, n) :
    buf = bytearray(n)
    view = memoryview(buf)
    while n:
        nbytes = sock.recv_into(view, n)
        view = view[nbytes:] # slicing views is cheap
        n -= nbytes
    return buf


def postgres_protocol_version_to_binary(major, minor) :
    return struct.pack('! I', major << 16 | minor)


if __name__ == '__main__':
    main()
Copy the code

To use: Copy the script get_postgres_cert.py

Python get_postgres_cert. Py 127.0.0.1:5432Copy the code