commit 4cf8499c32eecd4a5f027947789af602c8de3924 Author: Alexandre RIO Date: Tue Oct 14 21:43:08 2025 +0200 initial commit diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..2c07333 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11 diff --git a/README.md b/README.md new file mode 100644 index 0000000..d25054d --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +mDNS server +=== + +Minimalist mDNS server implementation with only core service annoucement and no conflict resolution. + +To test our implementation we’re using zeroconf as a trusted client. \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..6336a4b --- /dev/null +++ b/main.py @@ -0,0 +1,54 @@ +import socket +from dnslib import DNSRecord, DNSHeader, QTYPE, A, SRV, TXT, RR, PTR +import dns.message + +multicast_group = "224.0.0.251" +multicast_port = 5353 +interface_ip = "0.0.0.0" + +def main(): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32) + # See man socket(7) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + #sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + sock.bind(("", multicast_port)) + # sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip)) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(interface_ip)) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip)) + + while True: + received, sender = sock.recvfrom(1500) + print(f'Received packet of {len(received)} bytes from {sender}') + try: + msg = dns.message.from_wire(received) + except dns.exception.FormError: + print("Not a valid DNS message") + continue + + if msg.opcode() == dns.opcode.QUERY: + for question in msg.question: + if str(question.name) == '_http._tcp.local.': + print(f"question name {type(msg)}") + unicast_response = question.rdclass == 0x8001 + response = DNSRecord(DNSHeader(id = 0, bitmap=0x8400)) + ptr = PTR("toto._http._tcp.local") + srv = SRV(target="toto.local", priority=10, port=80, weight=100) + txt = TXT("path=/") + a = A("192.168.1.21") + response.add_answer(RR('_http._tcp.local', QTYPE.PTR, rdata = ptr, ttl=120)) + response.add_ar(RR('toto._http._tcp.local', QTYPE.SRV, rdata = srv, ttl=120)) + response.add_ar(RR('toto._http._tcp.local', QTYPE.TXT, rdata = txt, ttl=120)) + response.add_ar(RR('toto.local', QTYPE.A, rdata = a, ttl=120)) + print(str(response)) + if unicast_response: + print("Unicast response") + sock.sendto(response.pack(), sender) + else: + print("Multicast response") + sock.sendto(response.pack(), (multicast_group, multicast_port)) + print(f'Send response to {sender}') + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b82d5bd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "mdns" +version = "0.1.0" +description = "Minimalist mdns server" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [ + "dnslib>=0.9.26", + "dnspython>=2.8.0", +]