经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 网络安全 » 查看文章
SSL证书自签名使用及监控
来源:cnblogs  作者:freshchen  时间:2019/10/21 8:54:19  对本文有异议

前言

证书简介

信息安全越来越受重视,HTTPS已经相当普及,要让我们的HTTP接口支持HTPPS,只需要一个SSL证书就可以啦

  • 全称公钥证书(Public-Key Certificate, PKC),里面保存着归属者的基本信息,以及证书过期时间、归属者的公钥,并由认证机构(Certification Authority, CA)施加数字签名,表明,某个认证机构认定该公钥的确属于此人
  • 自签名的证书,就是我们来充当 认证机构,这种证书推荐在测试开发过程中,生产环境直接上CA证书省心!

实践

证书生成

准备

  • 确保有openssl库

  • 创建目录

    1. # 根证书目录
    2. [root@centos7 ~]# mkdir -p /var/ssl/crt/root
    3. # 服务器端证书目录
    4. [root@centos7 ~]# mkdir -p /var/ssl/crt/server

生成根证书

  • 私钥,RSA对称加密,aes比des更安全,密钥长度2048

    1. openssl genrsa -aes256 -out /var/ssl/crt/root/ca.key -passout pass:"123456" 2048
  • 请求流程,包含证书信息,其中比较关键的是CN,是填你的域名,根证书不起服务可以随便写

    1. 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/emailAddress=my@mail.com" -passin pass:"123456"
  • 颁发证书,这个生成的就是可以用的证书了,注意不加v3_ca这个插件,浏览器导入不了

    1. 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"

生成服务端证书

有了根证书之后,我们将所有的服务端证书都从根证书签出,方便客户端用根证书统一访问

  • 私钥,RSA对称加密,aes比des更安全,密钥长度2048

    1. openssl genrsa -aes256 -out /var/ssl/crt/server/svc1-server.key -passout pass:"123456" 2048
  • 请求流程,包含证书信息,其中比较关键的是CN,是填你的域名

    1. 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/emailAddress=my@mail.com" -passin pass:"123456"
  • 颁发证书,这个生成的就是可以用的证书了,注意不加v3_ca这个插件,浏览器导入不了

    1. 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"
  • 验证证书

    1. openssl verify -CAfile /var/ssl/crt/root/ca.crt /var/ssl/crt/server/svc1-server.crt

证书使用

Unubtu为例

  1. apt install nginx -y

配置

  1. vi /etc/nginx/sites-available/default
  2. # 到最后加上如下内容
  3. server {
  4. listen 443 ssl http2 default_server;
  5. listen [::]:443 ssl http2 default_server;
  6. server_name www.svc1.com;
  7. root /usr/share/nginx/html;
  8. ssl_certificate "/var/ssl/crt/server/svc1-server.crt";
  9. ssl_certificate_key "/var/ssl/crt/server/svc1-server.key";
  10. ssl_session_cache shared:SSL:1m;
  11. ssl_session_timeout 10m;
  12. ssl_ciphers HIGH:!aNULL:!MD5;
  13. ssl_prefer_server_ciphers on;
  14. include /etc/nginx/default.d/*.conf;
  15. location / {
  16. }
  17. error_page 404 /404.html;
  18. location = /40x.html {
  19. }
  20. error_page 500 502 503 504 /50x.html;
  21. location = /50x.html {
  22. }
  23. }
  1. vi /etc/hosts
  2. 127.0.0.1 www.svc1.com

启动

  1. root@CN-00013965:/# sudo service nginx restart
  2. * Restarting nginx nginx Enter PEM pass phrase:
  3. Enter PEM pass phrase: [ OK ]

测试

  • 不用证书 失败

    1. root@CN-00013965:/# wget https://www.svc1.com
    2. --2019-10-18 16:37:48-- https://www.svc1.com/
    3. Resolving www.svc1.com (www.svc1.com)... 127.0.0.1
    4. Connecting to www.svc1.com (www.svc1.com)|127.0.0.1|:443... connected.
    5. ERROR: cannot verify www.svc1.com's certificate, issued by ‘emailAddress=my@mail.com,CN=www.ca.crt.com,OU=mygroup,O=myorganization,L=mycity,ST=myprovince,C=CN’:
    6. Unable to locally verify the issuer's authority.
    7. To connect to www.svc1.com insecurely, use `--no-check-certificate'.
  • 用根证书访问 成功

    1. root@CN-00013965:/# wget --ca-certificate=/var/ssl/crt/root/ca.crt https://www.svc1.com
    2. --2019-10-18 16:39:50-- https://www.svc1.com/
    3. Resolving www.svc1.com (www.svc1.com)... 127.0.0.1
    4. Connecting to www.svc1.com (www.svc1.com)|127.0.0.1|:443... connected.
    5. HTTP request sent, awaiting response... 200 OK
    6. Length: 612 [text/html]
    7. Saving to: index.html.1
    8. index.html.1 100%[===================================================================================================================>] 612 --.-KB/s in 0s
    9. 2019-10-18 16:39:50 (32.4 MB/s) - index.html.1 saved [612/612]

导入Java应用

java应用要读取服务端证书需要通过pkcs12格式的keystore文件,我们可以把不同的服务端证书用别名区分。然后我们读取trustkeystore去访问HTTPS其他服务

  • 生成keystore

    1. 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"

    keytool命令是JDK自带的到${JAVA_HOME}/bin下执行,-srcstorepass是我们证书的密码,其他两个是keystore的密码

    1. 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"
  • 生成trustkeystore

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

监控

证书起到服务端口上了,我们怎么查看证书信息,或者实时检查证书过期信息呢,已默认443端口为例

  1. root@CN-00013965:/# echo 'Q' | timeout 5 openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -subject -dates
  2. subject=C = CN, ST = myprovince, L = mycity, O = myorganization, OU = mygroup, CN = www.svc1.com, emailAddress = my@mail.com
  3. notBefore=Oct 18 08:09:32 2019 GMT
  4. notAfter=Oct 15 08:09:32 2029 GMT

如果在用postgresql数据库起的HTTPS,那么直接openssl不能直接拿到端口证书,我们可以借助python脚本,脚本是Github上找的

  1. #!/usr/bin/env python
  2. import argparse
  3. import socket
  4. import ssl
  5. import struct
  6. import subprocess
  7. import sys
  8. try:
  9. from urlparse import urlparse
  10. except ImportError:
  11. from urllib.parse import urlparse
  12. def main():
  13. args = get_args()
  14. target = get_target_address_from_args(args)
  15. sock = socket.create_connection(target)
  16. try:
  17. certificate_as_pem = get_certificate_from_socket(sock)
  18. print(certificate_as_pem.decode('utf-8'))
  19. except Exception as exc:
  20. sys.stderr.write('Something failed while fetching certificate: {0}\n'.format(exc))
  21. sys.exit(1)
  22. finally:
  23. sock.close()
  24. def get_args():
  25. parser = argparse.ArgumentParser()
  26. parser.add_argument('database', help='Either an IP address, hostname or URL with host and port')
  27. return parser.parse_args()
  28. def get_target_address_from_args(args):
  29. specified_target = args.database
  30. if '//' not in specified_target:
  31. specified_target = '//' + specified_target
  32. parsed = urlparse(specified_target)
  33. return (parsed.hostname, parsed.port or 5432)
  34. def get_certificate_from_socket(sock):
  35. request_ssl(sock)
  36. ssl_context = get_ssl_context()
  37. sock = ssl_context.wrap_socket(sock)
  38. sock.do_handshake()
  39. certificate_as_der = sock.getpeercert(binary_form=True)
  40. certificate_as_pem = encode_der_as_pem(certificate_as_der)
  41. return certificate_as_pem
  42. def request_ssl(sock):
  43. version_ssl = postgres_protocol_version_to_binary(1234, 5679)
  44. length = struct.pack('!I', 8)
  45. packet = length + version_ssl
  46. sock.sendall(packet)
  47. data = read_n_bytes_from_socket(sock, 1)
  48. if data != b'S':
  49. raise Exception('Backend does not support TLS')
  50. def get_ssl_context():
  51. for proto in ('PROTOCOL_TLSv1_2', 'PROTOCOL_TLSv1', 'PROTOCOL_SSLv23'):
  52. protocol = getattr(ssl, proto, None)
  53. if protocol:
  54. break
  55. return ssl.SSLContext(protocol)
  56. def encode_der_as_pem(cert):
  57. cmd = ['openssl', 'x509', '-inform', 'DER']
  58. pipe = subprocess.PIPE
  59. process = subprocess.Popen(cmd, stdin=pipe, stdout=pipe, stderr=pipe)
  60. stdout, stderr = process.communicate(cert)
  61. if stderr:
  62. raise Exception('OpenSSL error when converting cert to PEM: {0}'.format(stderr))
  63. return stdout.strip()
  64. def read_n_bytes_from_socket(sock, n):
  65. buf = bytearray(n)
  66. view = memoryview(buf)
  67. while n:
  68. nbytes = sock.recv_into(view, n)
  69. view = view[nbytes:] # slicing views is cheap
  70. n -= nbytes
  71. return buf
  72. def postgres_protocol_version_to_binary(major, minor):
  73. return struct.pack('!I', major << 16 | minor)
  74. if __name__ == '__main__':
  75. main()

使用方法:复制上面脚本,文件名get_postgres_cert.py

  1. python get_postgres_cert.py 127.0.0.1:5432

原文链接:http://www.cnblogs.com/freshchen/p/11699458.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号