Do you know if there is any pattern/logic that could be used to distinguish between an IP address and an FQDN in python? I have a script that process user input which could be ip or fqdn and i would like to to ip validation checks if ip, and no validation check in case it is fqdn.
addy = "1.2.3.4"
a = addy.split('.')
match = re.search('^(([0-9]|[0-9][0-9]|[0-9][0-9][0-9]))$', a[0])
if match is not None:
if is_valid_ipv4(addy) == True:
# code continues
what is case addy is fqdn? I wish to call is_valid_ipv4 if input string is only an IP address. Do I need a pattern for FQDN? How to distinguish between IP and FQDN?
Python knows about IP addresses. Meanwhile, this answer gives a pretty good regexp for validating FQDNs.
import ipaddress
import re
addy = "192.0.2.1"
fqdn_re = re.compile('(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}\.?$)')
try:
ip_addy = ipaddress.ip_address(addy)
if ip_addy.version == 4:
print("IPv4 address")
elif ip_addy.version == 6:
print("IPv6 address")
except ValueError:
if fqdn_re.search(addy):
print("FQDN address")
else:
print("Invalid address")
Personally, I'd use regex. In Python you can use the re package.
Write a pattern for each (IP and FQDN) and see which gets a match (re.match()).
Here are some useful links:
Bulding a regex for an IP address
Test your regex patterns
Related
I have the following code:
while True:
try:
HOST = input(float(('Enter host IP'))
except ValueError:
print('Error. That is not a valid IP address.')
continue
I require the user to input an IP address. I wanted to set an error so that if he uses a letter he gets an error. How can I do that and why isn't my code working?
Try something like this
while True:
try:
HOST = input('Enter host IP: ')
if len(HOST.split(".")) != 4:
raise ValueError
for char in HOST:
if char not in "0123456789.":
raise ValueError
except ValueError:
print('Error. That is not a valid IP address.')
continue
else:
break
There is no need for the try/except. You just need an IP validation. This code should be working.
import re
while True:
HOST = input("Enter IP adress: ")
if re.match(
r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
HOST,
):
print(f"{inp} is valid IP adress")
break
else:
print("Enter valid IP adress")
I will begin by pointing out a few problems with your submitted code. First of all, your code will never exit the while loop, since you have provided no break out. Secondly, a valid IP address takes the form of something along the lines of 192.168.2.10 for IPV4 or "2001:0db8:0a0b:12f0:0000:0000:0000:0001" for IPV6, and which can never be interpreted as a float, so you will always generate a value error response. In order to validate an IP addfress correctly checkout the following check if a string matches an IP address pattern in python?.
import ipaddress
Host = None
while True:
try:
Host = ipaddress.ip_address(input('Enter host IP'))
break
except:
print('Error. That is not a valid IP address.')
continue
Hi everyone this is my first time doing PCAP programming using Python for the programming language, this is for a task for University and I have mostly got everything I need to complete the task except for one small detail.
I just need to get an output of the source and destination port numbers (HTTP Port 80 for example) associated with the IP addresses.
I'm happy for the answer to be a pointer to the right direction to help me work it out for myself. Otherwise if it's easier for it to be just answered, I would like a basic explanation on what was used and how it resolves the problem so I can understand it better for when I do more future PCAP programming in my studies and research.
This is being utilized on a Unix system running FreeBSD 10.3
I have tried using dpkt.tcp, dpkt.udp, dpkt.ip libraries as well as tried some socket libraries to see if I can achieve the result I am looking for, but not having much luck. I'll be honest, I'm not sure what I need to use.
EDIT: I did try using tcp.sport and tcp.dport, still had no luck.
The main area of focus is where I have added the comments.
import datetime
import time
import sys
import dpkt
import socket
def printPcap(pcap):
for (ts,buf) in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
if eth.type == dpkt.ethernet.ETH_TYPE_IP:
ip = eth.data
ipsrc = socket.inet_ntoa(ip.src)
ipdst = socket.inet_ntoa(ip.dst)
srcport = ??? ###Stuck here for source port
dstport = ??? ###Stuck here for destination port
if ip.p == dpkt.ip.IP_PROTO_TCP:
TCP = ip.data
iptype = 'tcp'
elif ip.p == dpkt.ip.IP_PROTO_UDP:
UDP = ip.data
iptype = 'udp'
len = str(ip.len)
ttl = str(ip.ttl)
###My current output
print '[' +str(datetime.datetime.utcfromtimestamp(ts))+ '] - ' \
+ipsrc+ ':' +srcport+ ' -> ' +ipdst+ ':' +dstport+ \
' ('+iptype+', len='+len+', ttl='+ttl+')'
except:
pass
SAMPLE EXPECTED OUTPUT:
[2018-08-16 02:48:10.238506] - 172.16.11.2:61016 -> 172.16.10.2:80 (tcp, len=52, ttl=63)
The problem is that your print statement is bogus, but you've hidden that with the "bare except". Using the bare except is considered very poor practice in python for exactly this reason. See also answers to this question: Should I always specify an exception type in `except` statements?
Specifically, your print statement is attempting to concatenate an integer to a string which isn't valid.
So, repaired, and with:
if ip.p == dpkt.ip.IP_PROTO_TCP:
TCP = ip.data
iptype = 'tcp'
srcport = TCP.sport
dstport = TCP.dport
elif ip.p == dpkt.ip.IP_PROTO_UDP:
UDP = ip.data
iptype = 'udp'
srcport = UDP.sport
dstport = UDP.dport
and this print statement, it works:
print("[{}] - {}:{} -> {}:{} ({}, len={}, ttl={})".format(
datetime.datetime.utcfromtimestamp(ts), ipsrc, srcport,
ipdst, dstport, iptype, len, ttl))
Finally, at the very least, I would change your except clause to something like this to detect such issues in the future:
except Exception as exc:
print("Exception: {}".format(exc))
(Note that I've used the python3-compatible print function syntax here, which also works fine with python2's print statement.)
EDIT:
One other thing just occurred to me. If the first IP packet encountered is neither TCP or UDP, srcport and dstport will not be defined and that will cause an AttributeError exception. Leaving that for you to clean up.
Perhaps use ip.data to get the TCP packet and the sport and/or dport?
ip = eth.data
if ip.p == dpkt.ip.IP_PROTO_TCP:
tcp = ip.data
print('source port: {}, dest port: {}'.format(tcp.sport, tcp.dport))
I am trying to get the ip address and broadcast address of my machine and after a lot of research netifaces works fine but the problem is ip address prints properly but when i wanted the broadcast address it gives the docker broadcast address as well as the 'lo' broadcast address but i wanted only 'lo' broadcast address and i am not sure how to get only the broadcast address associated with 'lo'. Please help me with some ideas. Also i am not sure that i have mentioned that wanted only 'lo' broadcast address but it also gives me dockers broadcast address as well.
Code:
import netifaces
interfaces=netifaces.interfaces()
for i in interfaces:
if i=='lo':
continue
iface= netifaces.ifaddresses(i).get(netifaces.AF_INET)
if iface != None:
for j in iface:
bd=(j['broadcast'])
print(bd)
Output:
192.169.x.x('lo'-broadcast)
175.17.x.x ('docker'-broadcast)
Why are you trying to get lo? That is typically local loopback and will always have 127.0.0.1. I just made this in a CentOS environment. If you are using Windows, just tweek the "ifconfig adapter-name" string... probably use "ipconfig /all" or something.
#! /usr/bin/python
import os
import re
def get_ip_data(ether_adapter):
ip_list = []
ip_data = os.popen("ifconfig " + ether_adapter)
for line in ip_data:
match1 = re.search(r'inet\s+(\d+.\d+.\d+.\d+)', line)
match2 = re.search(r'broadcast\s+(\d+.\d+.\d+.\d+)', line)
if match1:
ip = match1.group(1)
ip_list.append(ip)
if match2:
bcast = match2.group(1)
ip_list.append(bcast)
return ip_list
if __name__ == "__main__":
ethernet_card = "virbr0"
inet_list = get_ip_data(ethernet_card)
for element in inet_list:
print(element)
[root#server Desktop]# ./ip.py
192.168.122.1
192.168.122.255
In the client "virbr0" is the name of my wifi card. Just replace that with your wifi card or ethernet card name as a string.
Are there any existing libraries to parse a string as an ipv4 or ipv6 address, or at least identify whether a string is an IP address (of either sort)?
Yes, there is ipaddr module, that can you help to check if a string is a IPv4/IPv6 address, and to detect its version.
import ipaddr
import sys
try:
ip = ipaddr.IPAddress(sys.argv[1])
print '%s is a correct IP%s address.' % (ip, ip.version)
except ValueError:
print 'address/netmask is invalid: %s' % sys.argv[1]
except:
print 'Usage : %s ip' % sys.argv[0]
But this is not a standard module, so it is not always possible to use it.
You also try using the standard socket module:
import socket
try:
socket.inet_aton(addr)
print "ipv4 address"
except socket.error:
print "not ipv4 address"
For IPv6 addresses you must use socket.inet_pton(socket.AF_INET6, address).
I also want to note, that inet_aton will try to convert (and really convert it) addresses like 10, 127 and so on, which do not look like IP addresses.
For IPv4, you can use
socket.inet_aton(some_string)
If it throws an exception, some_string is not a valid ip address
For IPv6, you can use:
socket.inet_pton(socket.AF_INET6, some_string)
Again, it throws an exception, if some_string is not a valid address.
IPv4 + IPv6 solution relying only on standard library. Returns 4 or 6 or raises ValueError.
try:
# Python 3.3+
import ipaddress
def ip_kind(addr):
return ipaddress.ip_address(addr).version
except ImportError:
# Fallback
import socket
def ip_kind(addr):
try:
socket.inet_aton(addr)
return 4
except socket.error: pass
try:
socket.inet_pton(socket.AF_INET6, addr)
return 6
except socket.error: pass
raise ValueError(addr)
You can use the netaddr library. It has valid_ipv4/valid_ipv6 methods:
import netaddr
if netaddr.valid_ipv4(str_ip) is True:
print("IP is IPv4")
else:
if netaddr.valid_ipv6(str_ip) is True:
print("IP is IPv6")
Try
apt-get install python-ipaddr
or get the source code from here
I prefer ip_interface because it handles situations both with and without prefix mask, for example, both "10.1.1.1/24" as well as simply "10.1.1.1". Needless to say, works for both v4 as well as v6
from ipaddress import ip_interface
ip_interface("10.1.1.1/24").ip
ip_interface("10.1.1.1/24").ip.version
ip_interface("10.1.1.1").ip
ip_interface("10.1.1.1").ip.version
ipaddr -- Google's IP address manipulation package.
Note that a proposal to include a revised version of the package in the Python standard library has recently been accepted (see PEP 3144).
If you know for sure that the address is valid and only trying to decide whether it is ipv4 or ipv6, wouldn't it be sufficient to do just:
if ":" in address:
print("Ipv6")
else:
print("Ipv4")
how can one check if variable contains DNS name or IP address in python ?
This will work.
import socket
host = "localhost"
if socket.gethostbyname(host) == host:
print "It's an IP"
else:
print "It's a host name"
You can use re module of Python to check if the contents of the variable is a ip address.
Example for the ip address :
import re
my_ip = "192.168.1.1"
is_valid = re.match("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", my_ip)
if is_valid:
print "%s is a valid ip address" % my_ip
Example for a hostname :
import re
my_hostname = "testhostname"
is_valid = re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", my_hostname)
if is_valid:
print "%s is a valid hostname" % my_hostname
I'd check out the answer for this SO question:
Regular expression to match DNS hostname or IP Address?
The main point is to take those two regexs and OR them together to get the desired result.
print 'ip' if s.split('.')[-1].isdigit() else 'domain name'
This does not verify if either one is well-formed.