Availability of IP Address - Python - python

How to check the availability of an IP address in python?
For example, I wan't to change my system's IP address to 192.168.112.226 statically overriding the dhcp provided address. The default gateway is 192.168.112.1. But I wan't to check before if anyone is using 192.168.112.226 before assigning to myself.
Usually do this in command line from bash. I check with ping 192.168.112.226. If host is unreachable, I use 'ifconfig' and 'route' to assign it to myself.
How to automate this using python?
PS: I prefer python so that I can use python-notify to beautify the output whether success or failure.

This is so bad in so many ways I can't even explain how awfull this is.
Why do you want this? Could you please tell us that, and we could come up with a much better answer than this utterly uggly "sollution"?
If you have a Linux/Unix system, you can make your DHCP client to request the DHCP-server to give you a specific IP address if the DHCP server know it's free. How to do this depends on the distribution.
There are two problems I see that you will create with your "sollution".
As some other has written, you could check to see that the IP is "free" right now, but the machine that own that IP address might start right after your test. Using its IP address, wich you have kidnapped.
If the DHCP server don't know that you have kidnapped an IP address, it could give it out to someone else.
Whatever it will break the network for that computer and yours, generating lots of work, and possible anger for/to the network administrator. And you don't want that, do you?

Okay, if you want to use bash, you can import os module or subprocess module.
for example:
import os
command = os.system('pint 192.168.112.226')
if command == 0: #Sucess
#write os.system() and give it ifconfig and route commands as parameter.
else: print "This IP is used by another person in your network."
you can read more about os.system and subprocess in python, by importing them and writing help(subprocess) for example.

You can use socket.gethostbyaddr() to find if IP Address is being in use or not.
import sys, os, socket
# Stores the IP Address
ip_address = sys.argv[1]
try:
socket.gethostbyaddr(ip_address)
# If previous line doesn't throw exception, IP address is being used by someone
print "No"
except socket.herror:
# socket.gethostbyaddr() throws error, so IP is not being used at present
# You can write os.system() and give it ifconfig and route commands as parameter.
print "Yes"
The problem with this code is that method.gethostbyaddr() takes lot of time to throw socket.herror if IP address is not in use on the network.
If you name this script as isIPAvailable.py, then it can be called by:
python isIPAvailable.py 192.168.112.226

Related

Get IPv4 Address from python, even with vpn on

So I'm using socket to connect clients to the server. For that, I need the computer's ip. Currently, the best way I found is this:
socket.gethostbyname(socket.gethostname())
I then use requests to tell my clients about my ip, and they connect. The issue here is that when my vpn is on, I get another host and that causes the clients to be unable to connect.
But when I open command prompt and type ipconfig, I get the correct ip regardless of the vpn status. So I need to get the same ip as would be shown under IPv4 in command prompt, is this possible in python?
I'm trying to get the server to work on any device regardless of exceptions such as this.
Thanks!
The way you retrieve the IP addresses of your system (most systems these days have multiple) uses the hostname of your system and therefore depends on i.e. DNS and your local hosts file. It will only give you one address, and can be quite unreliable, as you have seen with your VPN.
I'd recommend using the netifaces package. With it you can retrieve a list of all network interfaces and all their addresses.
An example from the manual:
>>> addrs = netifaces.ifaddresses('en0')
>>> addrs[netifaces.AF_INET]
[{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
You should be able to install it with pip. The source repository is here: https://bitbucket.org/al45tair/netifaces
Yeah so I ran into this issue and it seems that ipconfig command does work, so I used the following. It calls ipconfig using subprocess and uses a regex pattern to match the ipv4 line. Since there's two ipv4 lines, and on my machine the VPN appeared as Unknown adapter WindscribeWireguard: before Wireless LAN adapter Wi-Fi: so I ended up matching the last one that appears. It's possible this isn't robust but I'm sure one of my users will let me know then.
from subprocess import check_output
import re
ipv4_pattern = re.compile(r'IPv4 Address.*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
def get_ipv4():
ipconfig_output = check_output(['ipconfig'], shell=True, text=True, encoding='iso8859-2')
return ipv4_pattern.findall(ipconfig_output)[-1]

socket.gethostbyname giving wrong IP

socket.gethostbyname("vidzi.tv") giving '104.20.87.139'
ping vidzi.tv gives '104.20.86.139'
socket.gethostbyname("www.vidzi.tv") giving '104.20.87.139'
ping www.vidzi.tv gives '104.20.86.139'
Why socket.gethostbyname is giving wrong IP for this website? It is giving right IP for other websites?
I don't see any "wrong" IPs in your question. A DNS server is allowed to return multiple IP addresses for the same host. The client generally just picks one of them. A lot of servers use this as a part of their load balancing, as clients select any available server and since they generally would pick different ones the traffic gets split up evenly. Your ping command and your gethostbyname command are just selecting different available IPs, but neither is "wrong".
You can see all the IPs that are returned for a given hostname with a tool like nslookup or dig.

Listen for a specific IP address? (Python 3.x)

I'm searching for a method to get a simple python server to listen for a specific local IP address on my LAN using the socket import (assuming the destination computer has a client script). socket.bind() and socket.listen(int) methods cannot provide me with any options for filtering IP addresses. Am I missing a method?
I don't think Python has a built-in method to do that.
However, as WhatsThePoint suggested, you can add your own filtering, as socket.recvfrom() will give you the client address, compare it with your required address, and if it's wrong, throw away the data.

Port forwarding in python to allow socket connections

I start a server using sockets and want to allow clients to connect to it.
self.sock.bind(('0.0.0.0',0)) # 0.0.0.0 will allow all connections and port 0 -> os chooses a open port.
stroke_port=self.sock.getsockname()[1]
self.sock.listen(75)
self.open_port_popup(stroke_port)
Now, for other clients to connect I have port forward it manually and it works fine.
I want to do this in automated fashion. -> I try upnp.
import miniupnpc
def open_port(port_no):
'''this function opens a port using upnp'''
upnp = miniupnpc.UPnP()
upnp.discoverdelay = 10
upnp.discover()
upnp.selectigd()
# addportmapping(external-port, protocol, internal-host, internal-port, description, remote-host)
result=upnp.addportmapping(port_no, 'TCP', upnp.lanaddr, port_no, 'testing', '')
return result
It opens a port shown in the image below. But the port-forwarding list shown in the first image is empty. It doesn't work and clients can't connect. How can I fix this? What am I missing?
I think you made a mistake using upnp.lanaddr as internal-host address. upnp.lanaddr is the address of the upnp device which is your router, you want to use the local address of your server.
If needed take a look at Finding local IP addresses using Python's stdlib if you want to get your server local IP dynamically.
I think that we are missing lot of related info to know what's the main problem here. I see so many people guessing.
By the way, just editing that line
result=upnp.addportmapping(port_no, 'TCP', upnp.lanaddr, port_no, 'testing', '') to
result=upnp.addportmapping('7777', 'TCP', '192.168.1.8', '7777', 'testing', '') would tell you if it works at all.
Doing port testing from localhost it's dummy, you're not under the router at all.
Also, remember to use Try/Except blocks to tell you what's wrong on your code.
try:
print "1" + 1
except Exception as e:
print str(e)
Another way, not fashioned is to use html/web automation, even cURL to make those requests instead using uPnp, this way you don't really need to handle it.
Most of the time ISP don't allow port forwarding, and you spend hours on this trying to forward port.
I went for ngrok - it's a lightweight free of cost (for basic usage) program that tunnels the port and give its own tunneled domain which can be accessed everywhere.
this is interesting question.
from what I could summon I think
GUI shows that UPNP port forwarding rules are added.
so Most likely there is issue in UPNPC configuration.
I doubt you are doing this on Router or similar platform with X-WRT or OpenWRT
the issue I think is you can't use upnp for this or it doesn't work for some strange reason.
I suggest you try this library pytables.
I know you wanted to know why and I am working on figuring out the reason.
this is just for you to get going on this project
and for quick solution
Try this
import subprocess
p = subprocess.Popen(["iptables", "-A", "INPUT", "-p", "tcp", "-m", "tcp", "--dport", "22" , "-j", "ACCEPT"], stdout=subprocess.PIPE)
output , err = p.communicate()
print output

socket.gethostbyaddr() returns error on some computers and not for others

I've looked for any other threads related to this topic, but after an extensive search i was not able to find an answer that relates to my question. Using Python, I'm trying to use socket.gethostbyaddr("ip here") to determine the hostname of an ip address in a local network:
import socket
def gethostname(ip):
hostname = socket.gethostbyaddr(ip)
return hostname
For some computers (such as the server) this returns the triplet of hostname, alias and other IP's, but for others it does not. Instead, i get the following error:
socket.herror: [Errno 4] No address associated with name
What exactly does this error imply? What could it be that causes it? Is there any service or instane that should be running on the target computer in order for this to work? The computers i'm trying to get the hostname of run Debian.
If this question has already been asked then i am sorry, but i could not find it.
If it has something to do with reverse dns lookups, how would i solve this?
It means exactly what it says, there is no address associated. Not all IP addresses have a reverse-lookup address.

Categories