import ssl, socket, time

if __name__ == "__main__":

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    #context.load_cert_chain(certfile=‘key_pub.pem’, keyfile=‘key_priv.pem')   #可以分开定义公钥和私钥文件,也可以合并成一个文件
    context.load_cert_chain(certfile=’cert.pem')
    
    bindsocket = socket.socket()
    bindsocket.bind(('127.0.0.1', 443))
    bindsocket.listen(5)
    
    newsocket, fromaddr = bindsocket.accept()
    connstream = context.wrap_socket(newsocket, server_side=True)
    
    try:
        data = connstream.recv(1024)
        print(data)
        buf = 'Hi NN%f\n\n\n\n'%time.time()
        buf = buf.encode()
        connstream.send(buf)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()
        bindsocket.close()

此例没有使用socketserver框架,目的在于测试ssl模块的用法。

继续,用框架实现HTTPS服务

import socketserver, ssl, time
class MyHTTPSHandler_socket(socketserver.BaseRequestHandler):
    def handle(self):
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.load_cert_chain(certfile="cert.pem")
        SSLSocket = context.wrap_socket(self.request, server_side=True)
        self.data = SSLSocket.recv(1024)
        print(self.data)
        buf = 'test HTTPS Server Handler<br>%f'%time.time()
        buf = buf.encode()
        SSLSocket.send(buf)

if __name__ == "__main__":
    port = 443
    httpd = socketserver.TCPServer(('localhost‘, port), MyHTTPSHandler_socket)
    print(’https serving at port', port)
    httpd.serve_forever()

说明:handle()函数负责所有与客户端的通信。客户端连接过来之后,ssl模块载入证书,并用SSLSocket对socket进行封装,屏蔽底层的加密通信细节。

下面再给出HTTPS文件服务器代码,文件访问功能由SimpleHTTPRequestHandler实现,数据加密传输由ssl实现。

import socketserver, ssl, time, http.server
class MyHTTPS_SimpleHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def setup(self):
        print('setup')
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.load_cert_chain(certfile=‘cert.pem’)
        SSLSocket = context.wrap_socket(self.request, server_side=True)
        self.rfile = SSLSocket.makefile('rb', self.rbufsize)
        self.wfile = SSLSocket.makefile('wb', self.wbufsize)
        
if __name__ == "__main__":
    port = 443
    httpd = socketserver.TCPServer(("localhost", port), MyHTTPS_SimpleHTTPRequestHandler)
    print('https serving at port', port)
    httpd.serve_forever()

最后,要指出的是setup()和handle()都是在客户端开始连接之后才被调用,从顺序上来说setup()先于handle()。

HTTPS Client in python with SSL Authentication

  1. import ssl, socket
  2.  
  3. key = mykeyfile
  4. cert = mycertfile
  5. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6. ssl_sock = ssl.wrap_socket(s,keyfile=key,certfile=cert,server_side=False)
  7. ssl_sock.connect(("www.xxx.xxx", 443))
  8. # This is where I call a method the server has exposed
  9. ssl_sock.callServerMethod(arg1,arg2)

How
to do mutual certificate authentication with httplib2

Here's the code my co-worker Dave St. Germain wrote to solve the problem:

  1. import ssl
  2. import socket
  3. from httplib2 import has_timeout
  4. import httplib2
  5. import socks
  6.  
  7. class CertificateValidationError(httplib2.HttpLib2Error):
  8. pass
  9.  
  10. def validating_sever_factory(ca_cert_file):
  11. # we need to define a closure here because we don't control
  12. # the arguments this class is instantiated with
  13. class ValidatingHTTPSConnection(httplib2.HTTPSConnectionWithTimeout):
  14.  
  15. def connect(self):
  16. # begin copypasta from HTTPSConnectionWithTimeout
  17. "Connect to a host on a given (SSL) port."
  18.  
  19. if self.proxy_info and self.proxy_info.isgood():
  20. sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
  21. sock.setproxy(*self.proxy_info.astuple())
  22. else:
  23. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  24.  
  25. if has_timeout(self.timeout):
  26. sock.settimeout(self.timeout)
  27. sock.connect((self.host, self.port))
  28. # end copypasta
  29.  
  30. try:
  31. self.sock = ssl.wrap_socket(sock,
  32. self.key_file,
  33. self.cert_file,
  34. cert_reqs=ssl.CERT_REQUIRED,
  35. ca_certs=ca_cert_file
  36. )
  37. except ssl.SSLError:
  38. # we have to capture the exception here and raise later because
  39. # httplib2 tries to ignore exceptions on connect
  40. import sys
  41. self._exc_info = sys.exc_info()
  42. raise
  43. else:
  44. self._exc_info = None
  45.  
  46. # this might be redundant
  47. server_cert = self.sock.getpeercert()
  48. if not server_cert:
  49. raise CertificateValidationError(repr(server_cert))
  50.  
  51. def getresponse(self):
  52. if not self._exc_info:
  53. return httplib2.HTTPSConnectionWithTimeout.getresponse(self)
  54. else:
  55. raise self._exc_info[1], None, self._exc_info[2]
  56. return ValidatingHTTPSConnection
  57.  
  58. def do_request(url,
  59. method='GET',
  60. body=None,
  61. headers=None,
  62. keyfile=None,
  63. certfile=None,
  64. ca_certs=None,
  65. proxy_info=None,
  66. timeout=30):
  67. """
  68. makes an http/https request, with optional client certificate and server
  69. certificate verification.
  70. returns response, content
  71. """
  72. kwargs = {}
  73. h = httplib2.Http(proxy_info=proxy_info, timeout=timeout)
  74. is_ssl = url.startswith('https')
  75. if is_ssl and ca_certs:
  76. kwargs['connection_type'] = validating_sever_factory(ca_certs)
  77.  
  78. if is_ssl and keyfile and certfile:
  79. h.add_certificate(keyfile, certfile, '')
  80. return h.request(url, method=method, body=body, headers=headers, **kwargs)

perhaps things have changed since your question, I am able to do mutual authentication withhttplib2 v0.7, as below:

  1. import httplib2
  2.  
  3. h=httplib2.Http(ca_certs='ca.crt')
  4. h.add_certificate(key='client_private_key.pem', cert='cert_client.pem', domain='')
  5. try: resp, cont = h.request('https://mytest.com/cgi-bin/test.cgi')
  6. except Exception as e: print e

ssl
certificate authentication in python

  1. s = socket.socket()
  2. print "connecting..."
  3. logging.debug("Connecting")
  4. # Connect with SSL mutual authentication
  5. # We only trust our server's CA, and it only trusts user certificates signed by it
  6. c = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED,
  7. ssl_version=ssl.PROTOCOL_SSLv3, ca_certs='ca.crt',
  8. certfile='user.crt', keyfile='user.key')
  9. c.connect((constants.server_addr, constants.port))
  1. Generally, you've acquired the CA certificate via some out-of-band method, then saved it locally. Linux systems generally have a bundle of certificates for well-known, trusted CAs available under  or similar.
  1. #!/usr/bin/env python
  2.  
  3. import httplib
  4.  
  5. CERTFILE = '/home/robr/mycert'
  6. HOSTNAME = 'localhost'
  7.  
  8. conn = httplib.HTTPSConnection(
  9. HOSTNAME,
  10. key_file = CERTFILE,
  11. cert_file = CERTFILE
  12. )
  13. conn.putrequest('GET', '/ssltest/')
  14. conn.endheaders()
  15. response = conn.getresponse()
  16. print response.read()

"mycert" is a PEM formatted certificate file that includes both the public certificate and the private key. If you read the code, you will notice that you can keep the public and private in seperate files if you care to.

SSL authentication generally requires that you set up your own certificate authority. You want to make sure you are the only one giving out keys to your empire.

Apache needs to be set up to require SSL client authentication. In my httpd.conf file I have the following:

SSLCACertificatePath /etc/httpd/conf/ssl.crt SSLCACertificateFile /etc/httpd/conf/ssl.crt/myCA.crt SSLVerifyClient require SSLVerifyDepth 2 SSLRequireSSL

If you have SSLCACertificateFile defined elsewhere in your config file, you'll need to resolve the conflict. It seems that Apache cannot refer to more than one SSLCACertificateFile. Multiple CA certs can exist in one file, but you may not want everyone with certs from all of your accepted CAs access to all of your content.

So why use SSL client authentication? It's a convenient way to do client authentication between web-enabled applications. It's good for SOAP or XML-RPC implementations, or custom apps that communicate via HTTP/HTTPS.

References: http://httpd.apache.org/docs-2.0/ssl/ssl_howto.html http://www.pseudonym.org/ssl/ssl_cook.html

class HTTPSConnection( host[, port, key_file, cert_file]) A subclass of HTTPConnection that uses SSL for communication with secure servers. Default port is 443. key_file is the name of a PEM formatted file that contains your private key. cert_file is a PEM formatted certificate chain file.

  1. Warning: This does not do any certificate verification!
  2. New in version 2.0.

If this doesn't do certificate verification, it seems to be very incomplete. Is there anyway to verify the certs or is this planned in a future release? The article/code snippet should state this defiency.


SSL Client Authentication over HTTPS (Python recipe)

A 16-line python application that demonstrates SSL client authentication over HTTPS. We also explain the basics of how to set up Apache to require
SSL client authentication. This assumes at least Python-2.2 compiled with SSL support, and Apache with mod_ssl



On the server, I'm initializing the SSLContext with my private key, the certfile provided by the CA that I'm loading from the caroot.crt file. Now, when I initialize this with something like node, everything works fine (for example: Setting
up SSL with node.js
). My intentions were to set everything up the same way. My assumption is that during the handshake, the server is providing the client with a CA, just like my node server would. It seems like that's not the case. What am I doing wrong?

If ssl.CERT_REQUIRED isn't used, everything works perfectly, but I'm wanting to validate that the endpoint (server) is who they say they are.

  1. # Server
  2. import socket
  3. import ssl
  4. context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  5. context.load_cert_chain(certfile='./path/to/certfile.crt',
  6. keyfile='./path/to/keyfile.pem')
  7. context.load_verify_locations('./path/to/caroot.crt')
  8. context.set_default_verify_paths()
  9. server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  10. server_socket.bind(('', 23000))
  11. server_socket.listen(socket.SOMAXCONN)
  12. def handle_client(ssl_socket):
  13. data = ssl_socket.read()
  14. while data:
  15. print("%s" % (str(data)))
  16. data = ssl_socket.read()
  17. while True:
  18. client_socket, addr = server_socket.accept()
  19. ssl_client_socket = context.wrap_socket(client_socket, server_side=True)
  20. handle_client(ssl_client_socket)
  21. # Client
  22. import socket
  23. import ssl
  24. context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  25. # I'm assuming this is not necessary, but I'd like to load the system provided CAs
  26. context.set_default_verify_paths()
  27. # Require CA validation to prevent MITM.
  28. context.verify_mode = ssl.CERT_REQUIRED
  29. client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  30. ssl_client = context.wrap_socket(client_socket)
  31. ssl_client.connect(('', 23000))
  32. ssl_client.send(bytes('hello, world!', 'UTF-8'))

As it turns out, my CA provided 3 different crt files. My solution was to append them in a specific order to generate the correct CA chain that was being passed to  For anyone using COMODO as a provider, here is a blog post:http://billpatrianakos.me/blog/2014/04/04/installing-comodo-positive-ssl-certs-on-apache-and-openssl/

Granted, that post is Apache specific, the premise is still the same. The command in question is:

  1. cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > yourdomain.com.cer

You then do:

  1. context.load_verify_locations('yourdomain.com.cer')

Everything now works as expected.

创建一个自签名的 SSL 证书

  1. #### 使用 OpenSSL 创建自签名证书
  2. ## 1.创建根证书的私钥
  3. openssl genrsa -out ca.key 1024
  4. ## 2.使用私钥创建根证书
  5. openssl req -new -x509 -days 36500 -key ca.key -out ca.crt
    -subj "/C=CN/ST=Fujian/L=Xiamen/O=Your Company Name/OU=Your Root CA"
  6. ## 3.创建服务器私钥
  7. openssl genrsa -out server.key 1024
  8. ## 4.使用服务器私钥创建证书请求文件
  9. openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=Fujian/L=Xiamen/O=Your Company Name/OU=youwebsite.org/CN=yourwebsite.org"
  10. ## 5.准备工作
  11. mkdir -p demoCA/newcerts
  12. touch demoCA/index.txt
  13. echo '01' > demoCA/serial
  14. ## 6.创建服务器证书并使用ca根证书签名
  15. openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
  16. ## ---查看不同格式文件的内容命令语法
  17. # openssl rsa -noout -text -in ca.key
  18. # openssl x509 -noout -text -in ca.crt
  19. # openssl rsa -noout -text -in server.key
  20. # openssl req -noout -text -in server.csr
  21. # openssl x509 -noout -text -in server.crt
  22. ## 创建证书最简单方式
  23. # openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.key

python server

  1. import socket, ssl
  2. import time
  3. cacrtf="ca/ca.crt"
  4. crtf="ca/server.crt"
  5. keyf="ca/server.key"
  6. server_sc = socket.socket()
  7. server_sc.bind(('', 10023))
  8. server_sc.listen(5)
  9. newsocket, addr = server_sc.accept()
  10. sc = ssl.wrap_socket(newsocket,
  11. server_side=True,
  12. certfile=crtf,
  13. keyfile=keyf,
  14. ca_certs=cacrtf)
  15. data = sc.read()
  16. print data
  17. sc.write('Back time: ' + str(time.time()))
  18. sc.close()
  19. server_sc.close()

python client

  1. import socket, ssl, pprint
  2. import time
  3. cacrtf="ca/ca.crt"
  4. crtf="ca/server.crt"
  5. keyf="ca/server.key"
  6. socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  7. ssl_socket = ssl.wrap_socket(socket, ca_certs=cacrtf, cert_reqs=ssl.CERT_REQUIRED)
  8. ssl_socket.connect(('127.0.0.1', 10023))
  9. print repr(ssl_socket.getpeername())
  10. print ssl_socket.cipher()
  11. print pprint.pformat(ssl_socket.getpeercert())
  12. ssl_socket.write("Time: %s\r\n" % time.time())
  13. data = ssl_socket.read()
  14. print data
  15. ssl_socket.close()

python ssl socket 的使用(服务器+客户端)

首先,使用如下命令生成证书和key:

openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem

接下来实现服务器:

import socket, ssl,time

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.load_cert_chain(certfile="cert.pem", keyfile="key.pem")

bindsocket = socket.socket()
bindsocket.bind(('191.8.1.235', 10023))
bindsocket.listen(5)

def do_something(connstream, data):
    #print("data length:",len(data))

return True

def deal_with_client(connstream):
    t_recv=0
    t_send=0
    n = 0
    t1=time.clock()
    data = connstream.recv(1024)
    t2=time.clock()
    print("receive time:",t2-t1)
    # empty data means the client is finished with us
    while data:
        if not do_something(connstream, data):
            # we'll assume do_something returns False
            # when we're finished with client
            break
        n = n + 1
        t1=time.clock()
        connstream.send(b'b'*1024)
        t2=time.clock()
        t_send += t2-t1
        print("send time:",t2-t1)
        t1=time.clock()
        data = connstream.recv(1024)
        t2=time.clock()
        t_recv +=t2-t1
        print("receive time:",t2-t1)
    print("avg send time:",t_send/n,"avg receive time:",t_recv/n)
    # finished with client

while True:
    newsocket, fromaddr = bindsocket.accept()
    connstream = context.wrap_socket(newsocket, server_side=True)
    try:
        deal_with_client(connstream)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()

客户端:

import socket, ssl, pprint,time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# require a certificate from the server
ssl_sock = ssl.wrap_socket(s,
                           ca_certs="cert.pem",
                           cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('191.8.1.235', 10023))

pprint.pprint(ssl_sock.getpeercert())
# note that closing the SSLSocket will also close the underlying socket
n=0
t_send=0
t_recv=0
while n <1000:
    n = n+1
    t1=time.clock()
    ssl_sock.send(b'a'*100)
    t2=time.clock()
    t_send += t2-t1 
    print("send time:",t2-t1)
    t1=time.clock()
    data=ssl_sock.recv(1024)
    t2=time.clock()
    t_recv += t2-t1
    print("receive time:",t2-t1)
    #print(len(data))
print("avg send time:",t_send/n,"avg receive time:",t_recv/n)
#ssl_sock.send(b'')
ssl_sock.close()

网络服务器之HTTPS服务的更多相关文章

  1. backup服务器之rsync服务

    backup服务器之rsync服务   rsync是开源的.快速的.多功能的可实现全量及增量的本地或远程数据同步备份的优秀工具.它拥有scp.cp的全量复制功能,同时比scp.cp命令更优秀.更强大. ...

  2. iredmail邮件服务器之修改默认的web服务端口号

    安装iredmail之后,由于需要在路由器上做端口映射以便在外网访问webmail,因此端口不能和WEB服务的端口好冲突,所以需要修改邮件服务器的httpd服务的端口. 一.apache/httpd的 ...

  3. nginx配置SSL证书实现https服务

    在前面一篇文章中,使用openssl生成了免费证书 后,我们现在使用该证书来实现我们本地node服务的https服务需求.假如我现在node基本架构如下: |----项目 | |--- static ...

  4. Web服务器之iis,apache,tomcat三者之间的比较

    IIS-Apache-Tomcat的区别 IIS与Tomcat的区别 IIS是微软公司的Web服务器.主要支持ASP语言环境. Tomcat是Java Servlet 2.2和JavaServer P ...

  5. 搭建VPN服务器之PPTP

    搭建VPN服务器之PPTP 1. 查看系统是否支持PPP 一般自己的系统支持,VPS需要验证. [root@oldboyedu ~]# cat /dev/ppp cat: /dev/ppp: No s ...

  6. linux下维护服务器之常用命令

    linux下维护服务器之常用命令! 第1套如下: 正则表达式: 1.如何不要文件中的空白行和注释语句: [root@localhost ~]# grep -v '^$' 文件名 |grep -v '^ ...

  7. Nginx设置Https反向代理,指向Docker Gitlab11.3.9 Https服务

    目录 目录 1.GitLab11.3.9的安装 2.域名在阿里云托管,申请免费的1年证书 3.Gitlab 的 https 配置 4.Nginx 配置 https,反向代理指向 Gitlab 配置 目 ...

  8. Web服务器之Nginx详解(操作部分)

    大纲 一.前言 二.Nginx 安装与配置 三.Nginx 配置文件详解 四.Nginx 命令参数 五.配置Nginx提供Web服务 六.配置Nginx的虚拟主机 七.配置Nginx的用户认证 八.配 ...

  9. 阿里云服务器配置免费https服务

    过程总述 购买服务器,购买域名,备案 申请ssl证书 DNS验证 上传证书,配置nginx 很关键,打开端口!!!阿里云的443端口默认是不打开的 1.购买服务器,域名,备案 服务器我是买的阿里云的, ...

随机推荐

  1. 51nod1130(斯特林近似)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1130 题意: 中文题诶~ 思路: 直接斯特林公式就好了~ ...

  2. MySql中的字符数据类型

    MySql中的varchar类型 1.varchar类型的变化 MySQL数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255根据不同版本数据库 ...

  3. 3.通过现有的PDB创建一个新的PDB

    实验说明:创建PDB除了可以通过种子PDB创建外,现在测试通过一个现有的用户PDB克隆创建新的PDB数据库 实验步骤: 1.创建测试数据 SQL> alter session set conta ...

  4. 第十六篇:SWindow的布局属性pos2type及offset

    当窗口大小需要根据内容来确定时,使用XML布局可能需要做一些特殊的处理. 例如:不管窗口多大,我需要将该窗口相对于父窗口居中在XML中应该怎么处理? 如果窗口大小是固定的(如, 100 *100),这 ...

  5. eclipse通过ctrl+shift+t无法找到源文件类的解决方法

    通过ctrl + shift + t找对应的类时,类明明存在,并且也在编译路径下,但就是查找不到,一个可能的原因就是eclipse为类建立的索引出了问题. 解决的方法是:找到项目所在工作空间下的.me ...

  6. 违反完整约束条件 (XXX) - 未找到父项关键字

    这个主要是A表的一个字段主键做了B表的外键,往B表插入数据就会出现这种情况 今天其他总结: detached entity passed to persist 错误的引起的原因和解决办法 这个主要是因 ...

  7. 近半年MVC使用后的一些习惯

    半年前接新项目, 来了一个前端, 由于只有我前后台都会, 就做业务层+辅助前端显示, 于是我决定使用MVC 上面那句无关紧要的话让我改了好多遍, 转载请注明出处: http://www.cnblogs ...

  8. T-SQL Recipes之删除重复行

    准备基础数据 (1)创建辅助表,方便以后倾向于Set-base方式解决问题 -- Creating and Populating the Nums Auxiliary Table SET NOCOUN ...

  9. Bulk_Collect 调用方式集锦

    事先申明,本文所有示例都皆源于<Expert PL SQL Practices>这本电子书的第六章.小陈觉得在学习PLSQL的过程中,将来或许会用到,在此笔记一番. 正文如下: 首先准备基 ...

  10. Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_The49DayPersonalFullscreenGiftModel", referenced from: objc-class-ref in The49DayPersonalRoomGiftModel.o ld: symbol(s) not found for a

    Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_The49DayPersonalFullscreenGiftModel&q ...