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