Python ssl for connecting with cloudflare 1.1.1.1:853

I’m trying to connect to Cloudflare’s 1.1.1.1 using DNS over TLS using ssl library in python 3.6. Unfortunately, the code runs but nothing is received on socket. The connection is being successfully established with the 1.1.1.1:853 address. The message variable contains the hex representation of the DNS request payload according to the RFC.

It requests the IP address for www.example.com

import socket
import ssl
import binascii

HOST, PORT = '1.1.1.1', 853

def send_message(_message, sock):
    __message = _message.replace(" ", "").replace("\n", "")
    ms = __message
    print(ms)
    m = binascii.unhexlify(ms)
    print(m)
    sock.send(m)
    data = sock.recv(4096)
    print(data)
    return binascii.hexlify(data).decode("utf-8")

def connect():
    # CREATE SOCKET
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(100)

    # WRAP SOCKET
    context = ssl.create_default_context()
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    context.verify_mode = ssl.CERT_REQUIRED
    #context.load_cert_chain(keyfile='/etc/ssl/certs/Cloudflare.key')
    context.load_verify_locations('/etc/ssl/certs/ca-
certificates.crt')

    wrappedSocket = context.wrap_socket(sock, server_hostname=HOST)

    # CONNECT AND PRINT REPLY
    wrappedSocket.connect((HOST, PORT))
    print(wrappedSocket.getpeercert())

    # CLOSE SOCKET CONNECTION
    return wrappedSocket


def format_hex(hex):
    """format_hex returns a pretty version of a hex string"""
    octets = [hex[i:i+2] for i in range(0, len(hex), 2)]
    pairs = [" ".join(octets[i:i+2]) for i in range(0, len(octets), 2)]
    return "\n".join(pairs)


message = "00 3a AA AA 01 00 00 01 00 00 00 00 00 00 " \
"07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01"

conn = connect()
response = send_message(message, conn)
print(format_hex(response))

Any hint would be a great, thanks.

The first bytes of a TCP packet needs to contain the length of the message. I think it was calculated wrongly in your example. I got your script working with the following message string:

message = "00 1d AA AA 01 00 00 01 00 00 00 00 00 00 " \
"07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01"

I generated the message from a PHP implementation, which I think you will find useful:

1 Like

Thank you martin. Yes its working now.

From where did u downloaded the /etc/ssl/certs/ca-certificates.crt file ?
Thanks in advance

I would assume this is the system’s default trust store.

Thanks Sandro . But how do we construct the hexadecimal message ? Say If if have to resolve for www.google.com . How can i construct the corresponding hexa string ?

:wave: @melvil.mec,

It appears that @zubairashraf1992 is doing that with

-OG

Hi Melvil,

For the clear understanding I woulf suggest you to learn about the DNS packet and details of that.

You will get idea about the number of bytes and associated information with those bytes.

And for more help you can look at https://github.com/ZubairAshraf/DNS-to-DNS-over-TLS-proxy

Best of luck.