I am questioning the results of the ipcalc module (ipcalc) for Python (it seems that netaddr may be a better choice).
Let's take 192.168.1.25/30 as an example. In binary, the last octet is 00011001 AND 11111100 = 00011000, so I get 192.168.1.24 as the Network ID and the range 192.168.1.24 - 192.168.1.27.
Using ipcalc, when I specify
subnet = ipcalc.Network('192.168.1.25/30')
for x in subnet: print x
The output is
192.168.1.25
192.168.1.26
192.168.1.27
192.168.1.28
I am not understanding the inconsistency. When using CIDR notation, it seems that specifying both 192.168.1.24/30 and 192.168.1.25/30 (or .26/30 or .27/30) refer to the same subnet.
Is that correct? Is this just a bug in the ipcalc module?
There is an open bug for this at the moment: No way to resolve IP + Netmask to Network Object
And an earlier bug report that discuss the matter: Strange subnet calculations
But they have also added a function called network to get the network address from an IP. From the manual:
>>> localnet = Network('127.128.99.3/8')
>>> print localnet.network()
127.0.0.0
The manual specifically says that the constructor Network should take a network address as its first argument, not any IP in the network. Rather confusing if you ask me (especially since the above code block breaks that condition). I would at least read the code for the module before using it.
It's correct the subnet is 192.168.1.24/30 so the ips 192.168.1.24 to 192.168.1.27 make part of this network.
Related
I have the following ip address "192.168.2.65"
Is there a way to convert the last 2 octets to 0.
I found the following, but it only lets me replace the last one, i need to replace the last 2.
ip = 192.168.2.65
output='.'.join(ip.split('.')[:-1]+["0"])
print(output)
which gives me 192.168.2.0 and i would like to be 192.168.0.0
Index -1 means the last index. If you want to change two, change your index to -2.
output='.'.join(ip.split('.')[:-2]+["0", "0"])
You could also use a regex based approach here:
ip = "192.168.2.65"
output = re.sub(r'\.\d+\.\d+$', '.0.0', ip)
print(output) # prints 192.168.0.0
Dependant on the logic you are trying to apply.. if you are simply wanting to modify a string, the other answers are correct.
However, if you are looking to get the network address for the subnet an address resides in, you should handle the addresses correctly and use the ipaddress module.
This will assist in calculating the correct network & broadcast addresses, and allow you to check inclusions in networks etc.
import ipaddress
interface = IPv4Interface('192.168.2.35/255.255.0.0')
print(interface.network)
#192.168.0.0/16
print(interface.network.network_address)
#192.168.0.0
print(interface.network.broadcast_address)
#192.168.255.255
I am trying to simulate a TCP communication between two hosts with scapy.
My problem is, that I can't save the random IP addresses scapy generates for me.
This code
src_IP = RandIP()
print(src_IP)
print(src_IP)
print(src_IP)
gives me an output like this
234.200.98.20
147.3.56.17
135.102.142.49
So every time I access src_IP it has a new value.
Is there a way to save a random IP from scapy? So I could generated 2 IPs at the beginning of my function and use them as source and destination for my TCP communication.
I could generate the IPs myself, but I thought there had to be a more elegant solution to it.
BTW. non of the packets are going to be sent, they will be written into a PCAP file. Therefor I have to create both sides of the communication.
The accepted answer is a hack; it is correct (as in "it works and do what was asked"), but it is not the correct way to do that in Scapy.
The method you are looking for is ._fix(). It will work with any volatile value type.
src_IP = RandIP()._fix()
If you also need for example a random source port, you could do:
src_port = RandShort()._fix()
I found an answer.
RandIP() creates an instance of an object, and every time this object gets accessed, to print or do send a packet or something else, it generates a new IP.
So my solution is to cast it to a string
src_IP = str(RandIP())
print(src_IP)
print(src_IP)
print(src_IP)
And the output is just as intended
232.119.133.38
232.119.133.38
232.119.133.38
I have an ip address 1.2.3.4 with a subnet mask 255.255.255.0
I want to convert this to cidr notation
1.2.3.4/24
How do I do this in Python3?
Use the ipaddress module in the standard library.
An address plus a netmask is either a network or an interface, not an address. Given that you've got some of the host bits set (it's 1.2.3.4, not 1.2.3.0), either you've got an interface, or you've got a non-canonical name for a network; I'll assume it's an interface, so use ip_interface:
>>> i = ipaddress.ip_interface('1.2.3.4/255.255.255.0')
Or, if you want to make sure it's explicitly IPv4 not IPv6:
>>> i = ipaddress.IPv4Interface('1.2.3.4/255.255.255.0')
Or you can compose it out of an address and a network, instead of out of a combined string. It depends on what format you have this information in and what makes sense to you.
To get the CIDR format, use the with_prefixlen accessor:
>>> i.with_prefixlen
'1.2.3.4/24'
You can also do all kinds of other nifty things—extract the address (1.2.3.4) as i.address, or the network (1.2.3.0/24) as i.network, or enumerate all the addresses on the network by treating i.network as a sequence, etc.
You can use the IPy library to do this. If you scroll down to the documentation you can see the string conversions it can do. The one we're after is strNormal(1)
IP("1.2.3.4/255.255.255.0").strNormal(1)
Given the range xxx.xxx.xxx.(195-223)
Is that correct to write it in xxx.xxx.xxx.196/29 and check whether an IP is in the given network by doing
from ipaddr import IP, CIDR
#if IP('xxx.xxx.xxx.xxx') in IP('xxx.xxx.xxx.196/29') or
#if IP('xxx.xxx.xxx.xxx') in CIDR('xxx.xxx.xxx.196/29')
I didn't see IP in ipaddr, only IPAddress.
May be like this?
from ipaddr import IPAdddress, IPNetwork
if IPAddress('10.0.0.195') in IPNetwork('10.0.0.196/29'):
pass
I haven't used the ipaddr module, but note that /29 means that your network mask is 255.255.255.248 and that you only have the latest 3 bits to address 2^3 = 8 different hosts in your network ranging from xxx.xxx.xxx.248 to xxx.xxx.xxx.255. That's outside of the range you want to check.
For more information, please have a look at the subnetwork wikipedia page.
For purpose of creating bulk virtual machines, I need to create a random MAC address generator in Python. I don't know how to generate random MAC addresses.
Is the following program correct or not?
import random
# The first line is defined for specified vendor
mac = [ 0x00, 0x24, 0x81,
random.randint(0x00, 0x7f),
random.randint(0x00, 0xff),
random.randint(0x00, 0xff) ]
print ':'.join(map(lambda x: "%02x" % x, mac))
For anyone wanting to generate their own MAC addresses (a good example is for VM NICs), you probably just want this:
"02:00:00:%02x:%02x:%02x" % (random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255))
Or, if you want to do this in a unix'y shell, this works on many:
printf '02:00:00:%02X:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))
This gives you a unicast MAC address that is 100% safe to use in your environment, and isn't trampling on anyone's registered MAC address space.
More detail...
The bottom two bits of the top byte (0x02) give you a locally administered unicast address, which is probably what you want if you are hitting stackoverflow for how to generate this. :)
If the MAC address is not locally administered, it means it is supposed to be "globally unique". MAC addresses in this category are centrally registered with the IEEE, and you should have a unique OUI (Organizationally Unique Identifier) issued to you by the IEEE. See this link for the global registry of OUI values. This OUI value ends up in the first 3 bytes (or just the top 22 bits, really).
MAC addresses aren't that complicated, so you should probably also just have a look at the definition. Wikipedia has a good one.
Modified from mamofish's code to Python3:
mac = '00:00:00:'
for number in range(16**6):
hex_num = hex(number)[2:].zfill(6)
print("{}{}{}:{}{}:{}{}".format(mac,*hex_num))
Generates mac addresses as strings from 00:00:00:00:00:00 to 00:00:00:ff:ff:ff.
Since uniqueness is all you should care about (beyond making the address well-formed), I'd worry about the MSBs in the OUI and use a sequence in the NIC specific bytes. The distribution of the addresses is likely unimportant to your application (even though some NIC or switch implementations might use them as an input to a hash, this is likely not to be a big concern).
You may want to consider using the "locally administered" flag in the OUI to avoid a conflict with an existing device manufacturer.
Avoid pitfalls like setting the multicast bit (your example does).
To avoid duplicates:
If you're going to generate a LOT (millions) of such MAC addresses, you might want to generate an in-order list of MAC's, feed that to a linear randomization process (GNU sort -R should do fine - I don't think it does this in linear time, but it has a similar end result) once, and then pull your fresh addresses off one end of the randomized list as needed. I believe such a list should fit in about 34 megabytes.
If you merely need thousands, you're probably better off maintaining a text file with already-selected values, and checking for collisions against that, adding new values as you go. This is a slower algorithm asympotically speaking, but it has a much less overhead, so it should still be a win for lower numbers of mac addresses.
BTW, should the 4th octet (numbered from 1 starting on the left), be 0-ff instead of 0-7f? I see no occurrences of 7f or 127 in the Wikipedia page on Mac addresses:
http://en.wikipedia.org/wiki/MAC_address