DNS Request with Scapy over IPv6 - python

I've seen many examples of how to send DNS requests via Scapy, but none for IPv6. For reference, I'm using Python 3, and ping6 ipv6.google.com is successful for me, so I seem to have a proper gateway. I'm trying to combine https://www.packetlevel.ch/html/scapy/scapyipv6.html and https://thepacketgeek.com/scapy-p-09-scapy-and-dns/, but I'm not sure how to do so exactly (just replacing IP(dst=dst) with IPv6(dst=dst) doesn't work). For reference, I've been trying to resolve "google.com" with Googles DNS Server (https://developers.google.com/speed/public-dns/docs/using).
Edit: I wish to be able to choose the DNS server I reach. For IPv4, I could do so with the following:
sr1(IP(dst=dns_dst)/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname=query_name)))

IPv6 Ping:
sr1(IPv6(dst="www.google.com")/ICMPv6EchoRequest(),timeout=3)
That would make a simple IPv6 packet with an echo request on top, and send/receive it on level 3
DNS over IPv6 on Google's public server, requesting an IPv6 address:
sr1(IPv6(dst="2001:4860:4860::8888")/UDP()/DNS(qd=DNSQR(qname="www.google.com", qtype="AAAA")))

Related

Multihomed UDP Python servers listening on 0.0.0.0

Since there is no support of IP_PKTINFO in python(for IPv4), are there no multihomed UDP python servers out there in production?
If there are ( and I expect there shall be), how do they handle the problem of sending the response UDP packets to the interface from which they received the request!
EDIT for clarification
Lets say I have a UDP server with multiple interfaces (consider 2 here), each with IP 172.217.163.68 and 172.217.163.69 respectively. The server has socket bind call on 0.0.0.0. Now if a request packet comes on 172.217.163.68, the server processes it, forms a response packet, and then sends on what interface? There is no way it knows about the interface from which request packet arrived, so it can't fill the sending interface IP. This is because there is no support for IP_PKTINFO in python.
Also it should be noted that we can't make use of the default route here. If default route gets used, then from the perspective of the client, it sent request to 172.217.163.68 but is getting response from 172.217.163.69, which is obviously wrong.
UDP servers use recvfrom and sendto to get the source IP address and to send back the response:
Receive:message, address = socket.recvfrom(1024)
Send: socket.sendto(message, address)
You can see an example UDP server in python in this question

DNS Server Commands

I use socket module in python to connect to dns server on a router.The connection is succesful and if I send a message I get a blank reply but what are commands that I can write to dns server?
Router is a Huawei Hg552e
gateway: 192.168.1.1
dns server port: 53
The commands are not clear-text, so you need to read the protocol specification and implement it, or use a library that already implements that for you, for example, PyUnbound.
See RFC 1035 - DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION.

difference between finding ip address by python an cmd

I wrote this code for finding google ip in python
import socket
print socket.gethostbyname('google.com')
.
.
173.194.39.0
but if we use command prompt and ping command for finding google ip result is:216.58.208.36
why there is difference between two results?
Both of those IP addresses resolve to Google.com. We can verify this from the command line with the unix whois command.
$ whois 216.58.208.36
NetRange: 216.58.192.0 - 216.58.223.255
CIDR: 216.58.192.0/19
NetName: GOOGLE
$ whois 173.194.39.0
NetRange: 173.194.0.0 - 173.194.255.255
CIDR: 173.194.0.0/16
NetName: GOOGLE
I ran into this same issue and the cause was that the first command that required an IP address was using a cached DNS entry (because the DNS entry's time to live (TTL) hadn't expired yet) and then by the time the second command was issued the TTL had expired on the cached entry so a new DNS request was made for the domain therefore grabbing a new IP address from the DNS server which happened to be different because the domain had a lot of IP addresses just like Google.com.
Python just relies on the Operating System's DNS resolver (or whatever daemon is running) and as far as I know the socket module doesn't give you the ability to clear the DNS cache before it tries to resolve an address. If you want more control over this functionality you can use DNSPython or something similar. If you are using a daemon for DNS on your operating system (like on Linux, for example) then usually restarting the daemon will force a flush of DNS cache and you find both addresses to the be same (unless you run into the timing issue as described above with the TTL's expiring).
Hostnames are translated to IP addresses through something called a DNS server. When you type a name into a web browser or use a program such as ping, the hostname that you provide (google.com) eventually reaches an authoritative DNS server for that domain-separate from the server that you correspond with for the actual content.
google.com has multiple different servers that can respond to data requests. Depending on the implementation of the different programs you are using to generate the request and other factors such as the network traffic at the time that you make the request, multiple requests from the same host may be directed to different servers by the authoritative DNS server. This is accomplished by returning different IP addresses to your machine.
FWIW, both ping and socket.gethostbyname() for google.com resolve to 216.58.217.14 on my machine, running OS X Yosemite.

Python dhcp client

I'm trying to learn how to directly (no libraries) send DHCP request from python on multi-homed machine (multiple interfaces).
I've looked at pydhcplib, but still do not get it.
This code send DHCP packet on specific interface (eth3 in my case - no IP assigned), but it sends with eth0 IP address. How to change my src IP to 0.0.0.0?
dhcp-message is truncated in this example
LOCAL_PORT=68
SERVER_PORT=67
LOCAL_IP="0.0.0.0"
BCAST_IP="255.255.255.255"
LISTEN_DEV="eth3"
MSG_SIZE=2048
Conn=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Conn.settimeout(5)
Conn.setsockopt(socket.SOL_SOCKET,IN.SO_BINDTODEVICE,LISTEN_DEV+'\0')
Conn.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
Conn.bind((LOCAL_IP, LOCAL_PORT))
# Create DHCP-Discovery
msg="010106003f7d1664......"
Conn.sendto(msg.decode("hex"),(BCAST_IP,SERVER_PORT))
received = Conn.recv(MSG_SIZE)
Conn.close()
I assume you already know about the Advanced Interprocess Communication Tutorial.
Spoiler Alert: If you want to jump straight to the bottom line, have a look at the DHCP Query recipe.
Edit:
The special value INADDR_ANY (0.0.0.0, or the empty string '' in a python socket) is not an IP address.
"When an address is specified as INADDR_ANY (a manifest constant
defined in < netinet/in.h >), the system interprets the address as 'any
valid address'."
From RFC 2131:
In the case of a client using DHCP for initial configuration
(before the client's TCP/IP software has been completely
configured), DHCP requires creative use of the client's TCP/IP
software and liberal interpretation of RFC 1122. The TCP/IP
software SHOULD accept and forward to the IP layer any IP packets
delivered to the client's hardware address before the IP address is
configured; DHCP servers and BOOTP relay agents may not be able to
deliver DHCP messages to clients that cannot accept hardware
unicast datagrams before the TCP/IP software is configured.
Presumably you're running this program on a system where the ethernet interfaces have already been configured and have valid IP addresses. I'm not sure why you'd want the source IP address to be 0.0.0.0, but perhaps you could set the interface IP to 0.0.0.0 with ifconfig to get the effect you want.
Or you could use a RAW socket and build the IP and UDP headers yourself to contain anything.

how to check if an ip address or proxy is working or not

How can I check if a specific ip address or proxy is alive or dead
Because there may be any level of filtering or translation between you and the remote host, the only way to determine whether you can connect to a specific host is to actually try to connect. If the connection succeeds, then you can, else you can't.
Pinging isn't sufficient because ICMP ECHO requests may be blocked yet TCP connections might go through fine.
Maybe this question here will help, its about pinging in python.
Post
An IP address corresponds to a device. You can't "connect" to a device in the general sense. You can connect to services on the device identified by ports. So, you find the ip address and port of the proxy server you're interested in and then try connecting to it using a simple socket.connect. If it connects fine, you can alteast be sure that something is running on that port of that ip address. Then you go ahead and use it and if things are not as you expect, you can make further decisions.

Categories