How to assign IP address to interface in python? - python

I have python script that set the IP4 address for my wireless and wired interfaces. So far, I use subprocess command like :
subprocess.call(["ip addr add local 192.168.1.2/24 broadcast 192.168.1.255 dev wlan0"])
How can I set the IP4 address of an interface using python libraries?
and if there is any way to get an already existing IP configurations using python libraries ?

With pyroute2.IPRoute:
from pyroute2 import IPRoute
ip = IPRoute()
index = ip.link_lookup(ifname='em1')[0]
ip.addr('add', index, address='192.168.0.1', mask=24)
ip.close()
With pyroute2.IPDB:
from pyroute2 import IPDB
ip = IPDB()
with ip.interfaces.em1 as em1:
em1.add_ip('192.168.0.1/24')
ip.release()

Set an address via the older ioctl interface:
import socket, struct, fcntl
SIOCSIFADDR = 0x8916
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def setIpAddr(iface, ip):
bin_ip = socket.inet_aton(ip)
ifreq = struct.pack('16sH2s4s8s', iface, socket.AF_INET, '\x00' * 2, bin_ip, '\x00' * 8)
fcntl.ioctl(sock, SIOCSIFADDR, ifreq)
setIpAddr('em1', '192.168.0.1')
(setting the netmask is done with SIOCSIFNETMASK = 0x891C)
Ip addresses can be retrieved in the same way: Finding local IP addresses using Python's stdlib
I believe there is a python implementation of Netlink should you want to use that over ioctl

You have multiple options to do it from your python program.
One could use the ip tool like you showed. While this is not the best option at all this usualy does the job while being a little bit slow and arkward to program.
Another way would be to do the things ip does on your own by using the kernel netlink interface directly. I know that libnl has some experimental (?) python bindings. This may work but you will have to deal with a lot of low level stuff. I wouldn't recommend this way for simple "set and get" ips but it's the most "correct" and reliable way to do so.
The best way in my opinion (if you only want to set and get ips) would be to use the NetworkManagers dbus interface. While this is very limited and may have its own problems (it might behave not the way you would like it to) this is the most straight forward way if the NetworkManager is running anyway.
So, choose the libnl approach if you want to get your hands dirty, it's clearly superior but also way more work. You may also get away with the NetworkManager dbus interface, depending on your needs and general system setup. Otherwise you can just leave it that way.

Related

Can sockets in python be used without internet access

I'm trying to send data from one software to another running on the same pc. The coding in the former s/w is done in python. I'm doing this:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("msg,Hi!", ("127.0.0.1", 12345))
This works fine when I have internet access (AF_INET). However, this is just a sample code and I will need to include this piece in some other application where I will not have internet access and so AF_INET wouldn't work. Is there a possible replacement for this?
I've already tried AF_UNIX and AF_LOCAL but neither of them works. I need to use UDP.
AF_INET has nothing to do with the INTERNET. It just means use IP based communication. You can do it on the same computer or across computers. 127.0.0.1 refers to local-host IP i.e. my own IP. Each unix/linux machine has the same local IP.
So yes this code will work without internet access.
Of course, You do not need any Internet concepts while using Sockets. You can use an ad-hoc network to create a relaxed network and run a simple TCP or UDP socket script to transfer things you like.
You can infact use Multicasting or Broadcasting schemes to share data on different devices within the ad-hoc network.

Sending raw IP Traffic with Python: Detect MTU

How can I implement a manual MTU discovery with Python?
From: https://networkengineering.stackexchange.com/a/28988/23983
Send a ping to a target, in my example, I'll use Google's DNS server (8.8.8.8). Set your DF bit in your ping to on, to prevent your ping from being fragmented. Set your packet size to some large number, or the standard MTU of 1500. Note that some ping implementations set the size of just the payload, which means you have to account for the 8 byte ICMP header, and 20 byte IP header.
I'd like to add that you could to this with raw sockets as well.
scapy is a nice abstraction layer that does much of the magic for you, but in all fairness if you're going to go low you could go all the way for the learning experience. (Note that raw sockets require elevated permissions in most modern OS'es, and as you go deeper implementations may vary from Windows and Linux.)
import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
This will give you a raw packet based socket that literally delivers all the frames for you. It varies a bit between Windows and Linux but I'll stick to Linux in this answer. Also note that all outgoing packets might not get picked up by this socket, if you need that functionality (sniffing stuff) consider searching for promiscuous mode related hits.
All you need to do now is treat each packet as the segments they come or go in, for instance - unpacking a ethernet and IP frame would look something like this:
frame, meta = s.recvfrom(65565)
print(frame, meta)
ethernet = frame[0:14]
ethernet_segments = struct.unpack("!6s6s2s", ethernet)
mac_source, mac_dest = (binascii.hexlify(mac) for mac in ethernet_segments[:2])
ip = frame[14:34]
ip_segments = struct.unpack("!12s4s4s", ip)
ip_source, ip_dest = (socket.inet_ntoa(section) for section in ip_segments[1:3])
print('MAC Source:', b':'.join(mac_source[i:i+2] for i in range(0, len(mac_source), 2)))
print('MAC Dest:', b':'.join(mac_dest[i:i+2] for i in range(0, len(mac_dest), 2)))
print('IP Source:', ip_source)
print('IP Dest:', ip_dest)
Payloading would be "easy", considering you're building the packets yourself.
All be it not the most conventional of ways or the initially fastest way, but you'd be able to implement whatever you wanted.
Sending is just as easy, use struct and have a look at the many ICMP examples out there, including those with checksum calculations:
https://www.g-loaded.eu/2009/10/30/python-ping/
https://gist.github.com/pklaus/856268
Regarding MTU, this is logic you'd have to implement yourself because there's no pre-built library that does this that I'm aware of.
But this is my contribution to sending raw IP traffic with Python.
Sending anything raw in python, you are looking at using at using scapy.
For info on how to send ping messages:
http://www.secdev.org/projects/scapy/doc/usage.html#icmp-ping
To set the DF Flag:
IP(flags='DF')
For how to adjust the particular size so that you can simulate fragmentation:
Adding payload in packet (scapy)
Putting it all together:
data = "x" * 1473
ans,unans = sr(IP(dst="<target_ip>", flags='DF' )/ICMP() / Raw(load=data))
If you aren't actually that interested in creating these things raw, this question is a dup of: How to find mtu value of network through code(in python)?

Python Packet Sniffer and Sockets for Noobs

So I have some questions about sockets and sniffer programming...
I've just started programming and have a project where I would like to use information that is sent across my network.
I tried watching several videos on youtube that talk about this process a little, and tried to find better material to research it further, but I haven't been able to find a source that makes sense to me.
The code I included came from a video on youtube and seemed to make sense as they explained it, but I guess he might have been using Linux or something else because Windows did not support AF_PACKET. After some research I found that people use AF_INET, but I got the error:
OSError: [WinError 10043] The requested protocol has not been configured into the system, or no implementation for it exists
Is there a place or a way someone might be able to explain sockets a little bit for me? I don't plan to use windows for the final version of this project, and I also plan to modify it for bluetooth in the future, so I would like to learn the reasoning behind things if I can find a way to do that.
`
import socket
import struct
import textwrap
def main():
conn = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.ntohs(3))
while True:
raw_data, addr = conn.recvfrom(65535)
dest_mac, src_mac, eth_proto, data = ethernet_frame(raw_data)
print('\nEthernet Frame:')
print('Destination: {}, Source: {}, Protocol: {}'.format(dest_mac, src_mac, eth_proto, data[:14]))
#unpack ethernet frame
def ethernet_frame(data):
dest_mac, src_mac, proto = struct.unpack('! 6s 6s H', data[:14])
return get_mac_addr(dest_mac), get_mac_addr(src_mac), socket.htons(proto), data[14:]
#Get Mac Address
def get_mac_addr(bytes_addr):
bytes_str = map('{:02x}'.format, bytes_addr)
return ':'.join(bytes_str).upper()
main()
`
The OSes on which you use a socket for packet sniffing are:
Linux
Irix
Windows is not on that list (neither are anything with "BSD" in the name, OS X, Solaris, HP-UX, AIX, etc.). Linux and Irix both happen to use sockets to do sniffing, but that's just their choice (and they didn't choose the same type of socket, they just happened to choose sockets).
If you want to write a sniffer, you're probably best advised to use a wrapper around libpcap/WinPcap, and let them deal with the painful details of the way packet sniffing is done on a particular operating system. Wrappers for Python include pylibpcap and pcapy; I don't know whether either of them work on Windows with WinPcap.
(Note that you are not guaranteed to get Ethernet headers on sniffed packets; you should call pcap_datalink(), or whatever the wrapper's equivalent is, and check its return value - if it's not DLT_EN10MB, or the wrapper's equivalent, you won't be getting Ethernet headers.)
AF_INET raw sockets, on any platform, aren't going to give you Ethernet headers. I don't know what you'll get with a protocol argument of 3 - 3 is the Internet protocol number for GGP, as per RFC 823 Appendix A, and that protocol is ancient and not used as far as I know; you'll probably end up with a socket on which you can send GGP packets and from which you can receive GGP packets, for what that's worth (which is not much). (Also, the arguments to the socket() call in C are in host byte order, and Python probably works the same, so you probably don't want that socket.ntohs() in there, not that it'll make a difference.)

Handling Multiple Network Interfaces in Python

How can I do the following things in python:
List all the IP interfaces on the current machine.
Receive updates about changes in network interfaces (goes up, goes down, changes IP address).
Any python package available in Ubuntu Hardy will do.
I think the best way to do this is via dbus-python.
The tutorial touches on network interfaces a little bit:
import dbus
bus = dbus.SystemBus()
proxy = bus.get_object('org.freedesktop.NetworkManager',
'/org/freedesktop/NetworkManager/Devices/eth0')
# proxy is a dbus.proxies.ProxyObject
I have been using the following code,
temp = str(os.system("ifconfig -a | awk '$2~/^Link/{_1=$1;getline;if($2~/^addr/){print _1" "}}'"))
it will give the 'up' network interfaces
e.g. eth0, eth2, wlan0
No, no... You don't need to bother os.system() or dbus API.
What you really need is to use netlink API to implement this. Either use libnl interface (netlink.route.link) or handle netlink messages by yourself. Take a look at this example.

How can I perform a ping or traceroute using native python?

I would like to be able to perform a ping and traceroute from within Python without having to execute the corresponding shell commands so I'd prefer a native python solution.
If you don't mind using an external module and not using UDP or TCP, scapy is an easy solution:
from scapy.all import *
target = ["192.168.1.254"]
result, unans = traceroute(target,l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="www.google.com")))
Or you can use the tcp version
from scapy.all import *
target = ["192.168.1.254"]
result, unans = traceroute(target,maxttl=32)
Please note you will have to run scapy as root in order to be able to perform these tasks or you will get:
socket.error: [Errno 1] Operation not permitted
Running interpreters as root is often frowned upon on security grounds (and of course you DO need to have root permission to access the "raw" socked as needed by the ICMP specs of ping and traceroute!), but if you have no problems with that it's not hard -- e.g., this post(dead?) or this post give a workable ping, and Jeremy Hylton's old page has still-usable underlying code for ICMP (both ping and traceroute) though it's written for very old Python versions and needs a litte facelift to shine with modern ones -- but, the concepts ARE all there, in both the URLs I gave you!
The Webb Library is very handy in performing all kinds of web related extracts...and ping and traceroute can be done easily through it. Just include the URL you want to traceroute to:
import webb
webb.traceroute("your-web-page-url")
If you wish to store the traceroute log to a text file automatically, use the following command:
webb.traceroute("your-web-page-url",'file-name.txt')
Similarly a IP address of a URl (server) can be obtained with the following lines of code:
print(webb.get_ip("your-web-page-url"))
Hope it helps!
The mtrpacket package can be used to send network probes, which can perform either a ping or a traceroute. Since it uses the back-end to the mtr commandline tool, it doesn't require that your script run as root.
It also uses asyncio's event loop, so you can have multiple ongoing traceroutes or pings simultaneously, and deal with their results as they complete.
Here is a Python script to traceroute to 'example.com':
import asyncio
import mtrpacket
async def trace():
async with mtrpacket.MtrPacket() as mtr:
for ttl in range(1, 256):
result = await mtr.probe('example.com', ttl=ttl)
print(result)
if result.success:
break
asyncio.get_event_loop().run_until_complete(trace())
The loop with 'ttl' is used because the 'time-to-live' of an outgoing packet determines the number of network hops the packet will travel before expiring and sending an error back to the original source.
you might want to check out the scapy package. it's the swiss army knife of network tools for python.
ICMP Ping is standard as part of the ICMP protocol.
Traceroute uses features of ICMP and IP to determine a path via Time To Live values. Using TTL values, you can do traceroutes in a variety of protocols as long as IP/ICMP work because it is the ICMP TTL EXceeded messages that tell you about the hop in the path.
If you attempt to access a port where no listener is available, by ICMP protocol rules, the host is supposed to send an ICMP Port Unreachable message.
I wrote a simple tcptraceroute in python which does not need root privileges http://www.thomas-guettler.de/scripts/tcptraceroute.py.txt
But it can't display the IP addresses of the intermediate hops. But sometimes it is useful, since you can guess where the blocking firewall is: Either at the beginning or at the end of the route.

Categories

Resources