Does python ssl encrypt the data in both directions? - python-3.x

I implemented a TCP socket client/server for a service I want to run on a virtual machine.
Furthermore, I want to encrypt the data transfer in both directions using the python library ssl. Currently, my code looks like this:
Server:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.set_ciphers('ECDHE-ECDSA-AES256-GCM-SHA384')
context.load_cert_chain(certfile="cert.pem", keyfile="prKey.pem")
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((ip, port))
ssocket = context.wrap_socket(tcpsock, server_side=True)
Client:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations("cert.pem")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssock = context.wrap_socket(sock, server_hostname=server_ip)
I generated my private key + self-signed certificate with OpenSSL.
I recently met someone who seemed to know about encryption (I´m new to this topic), hence I asked him quite a lot about my code. He told me that TLS normally only encrypts traffic one way and that I needed mutual TLS, which is more complicated. Since he was not a python developer he could not give me specific advice for my code, so I searched on the internet and inside the SSL documentation.
I don´t know if this is an obvious/stupid question but I could not find a simple answer for if my server/client connection is encrypted from both sides.
I also used wireshark to track the traffic of my client/server:
I´m not sure how to interpret the output but every two lines the protocol says TLSv1.3 (in the dropdown description it says TLS 1.2 which should be correct regarding the chosen cipher) while in the other lines it says TCP. Does this mean that only one side uses TLS while the other side sends its data unencrypted?
Right now both (server and client) run on my localhost, later the server will be implemented on a virtual machine in my network.

Related

Python3 Socket Programming

I am creating a software in Python3 and I need to Communicate with Whole World.
How I can create a socket over the wide area network instead of local area network!
Or Does socket programming works in such a way that client is in another network???
Plz I Need Answer as soon as possible!
Here is a example
import socket
HOSTNAME = "the host name"
PORT = xxxx
my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
my_socket.connect((HOST, PORT))
And I suggest you reed the Documentaion for waht you need.

Python dh key too small, which side is faulty?

Using Python 3, I'm trying to connect using a SSL context to a remote SMTP host, but I get the following error:
[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1056)
Here's the code I use:
from smtplib import SMTP
import ssl, os, certifi
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=certifi.where())
ssl_context.options |= ssl.OP_NO_TLSv1
ssl_context.options |= ssl.OP_NO_TLSv1_1
ssl_context.load_cert_chain(os.path.join(certsdir, 'certificate.pem'), os.path.join(certsdir, 'id_rsa'))
ssl_context.load_dh_params(os.path.join(certsdir, 'dhparams.pem'))
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
smtp = SMTP(server_name)
smtp.connect((host, 25))
smtp.ehlo()
if smtp.has_extn('starttls'):
smtp.starttls(None, None, ssl_context)
smtp.ehlo()
smtp.mail(fromaddr)
smtp.rcpt(toaddr)
smtp.data(message)
smtp.quit()
Question: Is the issue on my end, or on the destination's server end? Is there something I can do to avoid this issue?
I use certifi for the list of certificates, that is based on Mozilla recommendations and is up-to-date.
Thank you for your help here.
Question: Is the issue on my end, or on the destination's server end?
The server is offering a weak DH key, the client (your script) wants a stronger key. The problem should usually be fixed at the server side. And note that your call of load_dh_params makes no sense since setting the DH key is only relevant for the server side.
Is there something I can do to avoid this issue?
Don't use DH ciphers in the first place. All modern clients support ECDHE ciphers which don't have this problem. DH is very slow anyway.
Usually the client would also choose a ECDHE cipher if offered and this error will not happen. While it might be that the TLS stack at the client is too old and prefers DH, such an old stack would usually not complain about a weak DH. It is thus more likely that the servers SSL stack is too old so that it does not offer the more modern ciphers the clients wants by default.
To make sure that no DH ciphers are offered by the client and thus ECDHE or RSA key exchange is used set the ciphers accordingly:
ssl_context.set_ciphers('DEFAULT:!DH')
Note though that RSA key exchange is considered obsolete too since it does not provide any forward secrecy. You might therefore try if the server can do without DH and without kRSA by using a cipher string of DEFAULT:!DH:!kRSA.

Basic UDP networking doesn't receive

I'm trying to learn UDP networking so I tried the simplest code to begin with. It's a python code client-server that works perfectly when I send data to localhost or to the LAN IP from the same computer, but it doesn't work when I try to send from my computer using the public IP, and also doesn't work from another computer using private network IP or public IP.
I did the port forwarding, created the input rules for windows firewall, turned off the router internal firewall, and it still doesn't work.
When I scan my port from canyouseeme.org or using netcat it says connection refused and port closed.
Maybe somebody can guess what is happening here or what may I do to succeed?
I write the code below in case it's needed.
Server:
import socket
UDP_IP = "0.0.0.0"
UDP_PORT = XXXX
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
message = data.decode()
print("received message:", message)
Client:
import socket
UDP_IP = "192.168.1.133"
UDP_PORT = XXXX
MESSAGE = "Hello, World!"
print("UDP target IP:", UDP_IP)
print("UDP target port:", UDP_PORT)
print("message:", MESSAGE)
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE.encode(), (UDP_IP, UDP_PORT))
Thanks in advance.
After some investigation I have found a partial solution. I'm posting an answer because it may help some people with similar problems, but it's not the best solution yet, so the issue is still there.
I found that there's no problem in communicating within a LAN if I completely disable the firewall in both computers. I don't know why the input rules or exceptions don't work.
For networking beyond the LAN I have tried successfully to use a virtual LAN (i.e. hamachi) and there's no necessity of port forwarding nor disabling the firewall. The bad thing about hamachi is that I don't control the protocol it uses, and I don't control the way of ensuring reliability.
For the applications I'm dealing with right now I probably have enough with this solution, but it would be interesting to know more.

require('https') vs require('tls')

I'm trying to create a very secure connection between client and server using Node.js, Express.js and TLS (1.2).
I think my problem is in understanding what TLS actually is - meaning what is being exchanged, when and how by who.
Anyhow, I'm searching the internet like a nutter (crazy person) to try and figure out following:
what does var tls = require('tls'); invoke?
what does var https = require('https'); invoke?
I can get tls working when using another node as a client, but in this case the client will be a user in a browser. Can I use both for a browser or only https??
Thanks
Let's indeed start with what TLS is.
TLS is a way to provide secure connections between a client and a server. It does this by providing a safe way for clients and servers to exchange keys so they can then use public-key cryptography to secure their transmission. The exact mechanism is found here, but it's really not important for this answer.
Now, what is https? Well first, let's talk about HTTP. HTTP is a protocol that defines how web servers and clients talk and exchange web pages or data. Basically, it includes a request from a client and the server responds with a numerical message, headers, and (optionally) a body. If you're familiar with writing web pages, this is obvious.
So now, finally, what is HTTPS? HTTPS is a version of HTTP using TLS to secure data. This means that clients and servers can use the same protocol they're used to, wrapped in encryption.
Now, let's talk about these in node.js.
When you use require('tls'), you're only using the encryption layer, without defining the protocol. This will work fine for anything that doesn't expect an exact protocol, such as your other node.js client.
When you use require('https'), you're specifically using HTTP over TLS. The https module is actually a subclass of the tls module! (Oops, actually, the https.Server is a subclass of tls.Server) This means that whenever you're using the https module, you're also using the tls one.
Now, the final question: What does the browser want? If you've been following everything I've said, you can see that the browser wants https. In fact, it's likely that most of the webpages you've visited today has been over https.

How to broker secure connection across firewalls using untrusted host?

I have an interesting network security challenge that I can't figure out the best way to attack.
I need to provide a way to allow two computers (A and B) that are behind firewalls to make a secure connection to each other using only a common "broker" untrusted server on the internet (somewhere like RackSpace). (the server is considered untrusted because the customers behind the firewalls won't trust it since it is on an open server) I can not adjust the firewall settings to allow the networks to directly connect to each other because the connections are no known ahead of time.
This is very similar to a NAT to NAT connection problem like that handled by remote desktop help tools (crossloop, copilot, etc).
What I would really like to find is a way to open an SSL connection between the two hosts and have the public server broker the connection. Preferably when host A tries to connect to host B, it should have to provide a token that the broker can check with host B before establishing the connection.
To add another wrinkle to this, the connection mechanism needs to support two types of communication. First, HTTP request/response to a REST web service and second persistent socket connection(s) to allow for real-time message passing.
I have looked at the techniques I know about like OpenSSL using certificates, OAuth, etc, but I don't see anything that quite does what I need.
Has anyone else handled something like this before? Any pointers?
You can solve your problem with plain SSL.
Just have the untrusted server forward connections between the client hosts as opaque TCP connections. The clients then establish an end-to-end SSL connection over that forwarded TCP tunnel - with OpenSSL, one client calls SSL_accept() and the other calls SSL_connect().
Use certificates, probably including client certificates, to verify that the other end of the SSL connection is who you expect it to be.
(This is conceptually similar to the way that HTTPS connections work over web proxies - the browser just says "connect me to this destination", and establishes an SSL connection with the desired endpoint. The proxy just forwards encrypted SSL data backwards and forwards, and since it doesn't have the private key for the right certificate, it can't impersonate the desired endpoint).
In general, SSL is packet-based protocol (for the purpose of solving your task). If you can have the host forward the packets back and forth, you can easily have SSL-secured communication channel. One thing you need is something like our SSL/TLS components, which allow any transport and not just sockets. I.e. the component tells your code "send this packet to the other side" or "do you have anything for me to receive?" and your code communicates with your intermediate server.

Resources