Self signed Certificate with Python SSL socket - python

I use a self signed certificate that I generated with the following command:
sudo make-ssl-cert generate-default-snakeoil
And copied it to my home directory.
If I run the following with this on server side:
from socket import socket, AF_INET, SOCK_STREAM
import ssl
def main():
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain('/home/hfurmans/ssl-cert-snakeoil.pem', '/home/hfurmans/ssl-cert-snakeoil.key')
host = "myipaddress"
port = 5432
my_socket = socket(AF_INET, SOCK_STREAM)
my_socket.bind((host, port))
my_socket.listen(1)
my_socket = context.wrap_socket(my_socket, server_side=True)
conn, addr = my_socket.accept()
print("Connection from: " + str(addr))
data = conn.recv(1024).decode()
print(data)
print("from connected user: " + str(data))
data = str(data).upper()
print("sending: " + str(data))
conn.send(data.encode())
conn.close()
if __name__ == "__main__":
main()
I substituded my IP address. But they are the same on server and client.
Here is the client code:
import socket
import ssl
hostname = "myipaddress"
context = ssl.create_default_context()
sock = socket.create_connection((hostname, 5432))
ssock = context.wrap_socket(sock, server_hostname=hostname)
print(ssock.version())
ssock.send("test")
If I run both scripts i get the following error.
This is the client error:
bash-3.2$ python3 client.py
Traceback (most recent call last):
File "client.py", line 8, in <module>
ssock = context.wrap_socket(sock, server_hostname=hostname)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1108)
And here is the server error:
Traceback (most recent call last):
File "server.py", line 27, in <module>
main()
File "server.py", line 16, in main
conn, addr = my_socket.accept()
File "/usr/lib/python3.6/ssl.py", line 1125, in accept
server_side=True)
File "/usr/lib/python3.6/ssl.py", line 407, in wrap_socket
_context=self, _session=session)
File "/usr/lib/python3.6/ssl.py", line 817, in __init__
self.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:852)

A self-signed certificate is a trick to pretend that the CA
is the certificate itself.
So we have to provide beforehand the client with this certificate
in order to trust it when it will be encountered.
In the client, after the creation of the SSL context,
I tried something similar to
context.load_verify_locations('/home/hfurmans/ssl-cert-snakeoil.pem')
and it worked.
( https://docs.python.org/3/library/ssl.html#ssl.SSLContext.load_verify_locations)
I only had to remove context.verify_mode = ssl.CERT_REQUIRED in
the server because I didn't provide my client with its own certificate,
but that was not the problem reported in your question.
Of course, for all of this to work, your certificate must have
the correct common-name.
If the client connects to myipaddress (as a hostname),
then the common-name of the certificate must be myipaddress too.

Related

Connecting to a Postgres Database over SSL using Sockets in Python

I am trying to connect to a Postgres Database using sockets to enforce a particular TLS version from the client in order to verify that the Database does not accept connections from the client which uses an older version of TLS like tlsv1.1. The connection is failing on handshake with the following error :
python test2.py
Traceback (most recent call last): File "test2.py", line 12, in
ssl_version=ssl.PROTOCOL_TLSv1_2) File "<>/python3.6/lib/python3.6/ssl.py", line 1232, in
get_server_certificate
with context.wrap_socket(sock) as sslsock: File "<>/python3.6/lib/python3.6/ssl.py", line 407, in wrap_socket
_context=self, _session=session) File "<>/python3.6/lib/python3.6/ssl.py", line 817, in init
self.do_handshake() File "<>/python3.6/lib/python3.6/ssl.py", line 1077, in do_handshake
self._sslobj.do_handshake() File "<>/python3.6/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake() ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:852)
The following is a snippet of the code:
import socket
import ssl
hostname = <DB_Endpoint>
context = ssl.create_default_context()
with socket.create_connection((hostname, 8200)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print(ssock.version())

How to make https server on sockets

I am trying to make a web server on sockets in python. I saw how to make https support for server from module http.server in python by wrapping its socket with a .pem certificate. I would like to make https support on my socket server. I have a self-signed certificate for a localhost and it worked for a ready-made server, but my server has an error:
Traceback(most recent call last):
File "webserver.py", line 84, in main
server.start_server()
File "C:\b\nw\12t\http_lite.py", line 103, in start_server
conn, addr = ssock.accept()
File "C:\Python37\lib\ssl.py", line 1188, in accept
server_side=True)
File "C:\Python37\lib\ssl.py", line 423, in wrap_socket
session = session
File "C:\Python37\lib\ssl.py", line 870, in _create
self.do_handshake()
File "C:\Python37\lib\ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c: 1076)
And also if I allow to open a site in a browser:
Traceback (most recent call last):
File "webserver.py", line 84, in main
server.start_server()
File "C:\b\nw\12t\http_lite.py", line 100, in start_server
conn, addr = ssock.accept()
File "C:\Python37\lib\ssl.py", line 1188, in accept
server_side=True)
File "C:\Python37\lib\ssl.py", line 423, in wrap_socket
session = session
File "C:\Python37\lib\ssl.py", line 870, in _create
self.do_handshake()
File "C:\Python37\lib\ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
OSError: [Errno 0] Error
My connection setup code looks like this:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, proto=0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind ((self.host, self.port))
s.listen(self.backlog)
ssock = ssl.wrap_socket(s,
server_side=True,
certfile='localhost.pem',
ssl_version=ssl.PROTOCOL_TLSv1)
in the while loop
conn, addr = ssock.accept()
....
Please help me figure out what I am doing wrong.
Sorry for my bad English.

How to handle https clients with sockets in python? Making proxy server

Im creating proxy server using sockets in python. I know how to handle http clients. But with https it doesnt work. I send to client message that everything is ok. Then i try to wrap client socket as a secure socket. But it doesnt work.
I got message:
Exception in thread Thread-14:
Traceback (most recent call last):
File "C:\Python37\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Даниил/Downloads/python/proxy_server/proxy_server.py", line 39, in __handle_client
self.__handle_https(client_sock, client_data, host, port)
File "C:/Users/Даниил/Downloads/python/proxy_server/proxy_server.py", line 62, in __handle_https
server_side=True)
File "C:\Python37\lib\ssl.py", line 1238, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs
File "C:\Python37\lib\ssl.py", line 423, in wrap_socket
session=session
File "C:\Python37\lib\ssl.py", line 870, in _create
self.do_handshake()
File "C:\Python37\lib\ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)
I have certificate with Common Name: localhost and i added it in browser. Even when I create certificate with Common Name of host (e.g. docs.python.org) and add it to browser it doesnt work.
Here is my code of handling https requests:
def __handle_https(self, client_sock, data, host, port):
client_sock.sendall(b'HTTP/1.1 200 Connection Established\r\n\r\n')
sclient = ssl.wrap_socket(client_sock,
certfile='server.crt',
keyfile='server.key',
server_side=True)
A HTTP proxy should only forward the data between client and server after the CONNECT request is done. It should not handle the TLS itself as you try. Instead it should forward the data unchanged so that there is an end-to-end TLS connection between the client to the server via the proxy.

ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF) (_ssl.c:661)

This is my code:
import ssl, socket
server ='10.10.10.9'
port = 50443
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock =ssl.wrap_socket(sock,ssl_version=ssl.PROTOCOL_SSLv3)
ssl_sock.connect((server, port))
return ssl_sock
I am Getting below error:
File "/home/ragav/trunk/lib/Ipdu.py", line 35, in open_socket
ssl_sock.connect((server, port))
File "/usr/local/lib/python2.7/ssl.py", line 876, in connect
self._real_connect(addr, False)
File "/usr/local/lib/python2.7/ssl.py", line 867, in _real_connect
self.do_handshake()
File "/usr/local/lib/python2.7/ssl.py", line 840, in do_handshake
self._sslobj.do_handshake()
ssl.SSLZeroReturnError: TLS/SSL connection has been closed (EOF) (_ssl.c:661)
This might be due to openssl version. check your openssl version if its 0.9 then that might be a reason for the error.
You can check openssl version in your python code using
print ssl.OPENSSL_VERSION

SSL verification python server/python

I am trying to write an https server and client. I have created a CA along with a private key and a self signed certificate for testing.
Here is my test server:
#!/usr/bin/env python
import socket, os
from SocketServer import BaseServer
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SimpleHTTPServer import SimpleHTTPRequestHandler
from OpenSSL import SSL
CERTIFICATE_PATH = os.getcwd() + '/CA/cacert.pem'
KEY_PATH = os.getcwd() + '/CA/private/key.pem'
class SecureHTTPServer(HTTPServer):
def __init__(self, server_address, HandlerClass):
BaseServer.__init__(self, server_address, HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file(KEY_PATH)
ctx.use_certificate_file(CERTIFICATE_PATH)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
self.server_bind()
self.server_activate()
class MemberUpdateHandler(SimpleHTTPRequestHandler):
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
def do_GET(self):
try:
print 'path:', self.path
print self.path.endswith('.txt')
if self.path.endswith('.txt'):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write("successful")
return
else:
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write("not successful")
except IOError:
self.send_error(404, 'What you talking about willis?')
def test(HandlerClass = MemberUpdateHandler,
ServerClass = SecureHTTPServer):
server_address = ('', 4242)
httpd = ServerClass(server_address, HandlerClass)
sa = httpd.socket.getsockname()
print "serving HTTPS on:", sa[0], "port:", sa[1], "..."
httpd.serve_forever()
if __name__ == '__main__':
test()
and my simple client:
#!/usr/bin/env python
import os
import httplib
import socket
KEY_FILE = os.getcwd() + '/CA/private/key.pem'
CERT_FILE = os.getcwd() + '/CA/certs/01.pem'
GET = "GET"
conn = httplib.HTTPSConnection('0.0.0.0', '4242', cert_file = CERT_FILE)
conn.request(GET, "/this.txt")
response = conn.getresponse()
print response.status, response.reason, response.read()
conn.close()
My problem arises when I try to add the
cert_file = CERT_FILE
if I remove that from the call, it works. But I don't think I am getting the validation I want.
Here is the error I get when trying:
On the server side:
Exception happened during processing of request from ('127.0.0.1', 55283)
Traceback (most recent call last):
File "/usr/lib/python2.6/SocketServer.py", line 281, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.6/SocketServer.py", line 307, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.6/SocketServer.py", line 320, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.6/SocketServer.py", line 615, in __init__
self.handle()
File "/usr/lib/python2.6/BaseHTTPServer.py", line 329, in handle
self.handle_one_request()
File "/usr/lib/python2.6/BaseHTTPServer.py", line 312, in handle_one_request
self.raw_requestline = self.rfile.readline()
File "/usr/lib/python2.6/socket.py", line 406, in readline
data = self._sock.recv(self._rbufsize)
Error: [('SSL routines', 'SSL23_READ', 'ssl handshake failure')]
And from the client:
File "HTTPSClient.py", line 19, in <module>
conn.request(GET, "/this.txt")
File "/usr/lib/python2.6/httplib.py", line 910, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.6/httplib.py", line 947, in _send_request
self.endheaders()
File "/usr/lib/python2.6/httplib.py", line 904, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 776, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 735, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 1112, in connect
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
File "/usr/lib/python2.6/ssl.py", line 350, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs)
File "/usr/lib/python2.6/ssl.py", line 113, in __init__
cert_reqs, ssl_version, ca_certs)
ssl.SSLError: [Errno 336265225] _ssl.c:337: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
What file am I supposed to send there? I have a CA certificate, a signed certificate and a private key. The documentation I have been able to find is quite sparse.
Based on this [documentation][1]
class httplib.HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout[, source_address]]]]]])
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.
**Warning This does not do any verification of the server’s certificate.**
I am not sure (not experienced with Python), but I believe key_file and cert_file are for client side authentication.
And you can take a look at this link regarding certificate validation:
http://code.activestate.com/recipes/577548-https-httplib-client-connection-with-certificate-v/

Categories

Resources