Regex Match on IP Address Before Known String - python

I'm using nmap to search for hostnames and related IPs on my local (home) network. I can pull a string that looks something like this:
Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-15 22:20 PST
Nmap scan report for 192.168.1.1
Host is up (0.00025s latency).
MAC Address: ZZ:ZZ:11:ZZ:ZZ:ZZ (Cisco-Linksys)
Nmap scan report for 192.168.1.2
Host is up (0.0084s latency).
MAC Address: ZZ:ZZ:A1:2E:ZZ:ZZ (Apple)
Nmap scan report for 192.168.1.9
Host is up (0.012s latency).
MAC Address: A4:ZZ:57:17:ZZ:ZZ (Seiko Epson)
Nmap scan report for 192.168.1.103
Host is up (0.036s latency).
MAC Address: ZZ:ZZ:6D:05:ZZ:ZZ (Apple)
I know that I can put together a regular expression to give me the IP address directly above the "Seiko Epson" line, but I cannot figure out how to do it.
I'm specifically looking for a way to find the IP address of the host that I'm searching for, I'm currently using:
(?:(?: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]?)
to find IP addresses, but I do not know how to augment this to find the IP address above a given string.

If you get the whole input as a single string, then
You firstly search for a fixed string Nmap scan report for,
nextly remember a sequence 0-9 or . (which should be there) as the output IP address,
then skip until the MAC addr part (containing :),
skip until the next opening paren,
and finally check if the string inside parens is Seiko Epson.
Example:
>>> inp='''Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-15 22:20 PST
... Nmap scan report for 192.168.1.1
... Host is up (0.00025s latency).
... MAC Address: ZZ:ZZ:11:ZZ:ZZ:ZZ (Cisco-Linksys)
... Nmap scan report for 192.168.1.2
... Host is up (0.0084s latency).
... MAC Address: ZZ:ZZ:A1:2E:ZZ:ZZ (Apple)
... Nmap scan report for 192.168.1.9
... Host is up (0.012s latency).
... MAC Address: A4:ZZ:57:17:ZZ:ZZ (Seiko Epson)
... Nmap scan report for 192.168.1.103
... Host is up (0.036s latency).
... MAC Address: ZZ:ZZ:6D:05:ZZ:ZZ (Apple)'''
>>> import re
>>> r1 = re.compile(r'Nmap scan report for ([0-9.]*)[^:]*[^(]*\(Seiko Epson\)')
>>> r1.search(inp).group(1)
'192.168.1.9'
The idea behind [^...]'s is finite state machine.

Related

Python change ip twice a day at certain time with schedule module, closing prompt

I want my computer to switch between 2 different IP configuration, everyday at two different time. I figured i could automate this with a python script.
import sys
sys.path.append(r"c:\users\user\appdata\local\packages\pythonsoftwarefoundation.python.3.10_qbz5n2kfra8p0\localcache\local-packages\python310\site-packages")
import os
import ipaddress
import socket
import time
import schedule
def firstIP():
hn = socket.gethostname()
ipa = socket.gethostbyname(hn)
print("Current IP: ",ipa)
os.system('netsh interface ip set address name="Wi-Fi" static 192.168.1.20 255.255.255.0 192.168.1.1')
os.system('netsh interface ip set dns name="Wi-Fi" static 8.8.8.8')
os.system('netsh interface ip set dns name="Wi-Fi" static 8.8.4.4 index=2')
print("IP ADRESS CHANGED!")
def secondIP():
hn = socket.gethostname()
ipa = socket.gethostbyname(hn)
print("Current IP: ",ipa)
os.system('netsh interface ip set address name="Wi-Fi" static 192.168.1.50 255.255.255.0 192.168.1.1')
os.system('netsh interface ip set dns name="Wi-Fi" static 8.8.8.8')
os.system('netsh interface ip set dns name="Wi-Fi" static 8.8.4.4 index=2')
print("IP ADRESS CHANGED!")
schedule.every().day.at("01:00").do(firstIP)
schedule.every().day.at("15:00").do(secondIP)
while True:
schedule.run_pending()
time.sleep(1)
I made this script and it seems to work, but for it to run i need to:
open cmd and run the script
leave the cmd open with the script running
is there a way for running the script once, closing the cmd window and the schedule will still work? as a sort of os chron job? or something similar, without leaving the prompt open?
Thank you

Dynamically change a value within a list

I have a list of hostnames which i am using to populate an SCP command to transfer a file from the remote server to my local server. The problem is, some of the hosts do not connect via hostname, and i must use the IP. However this issue with this is that the file i want to transfer has the hostname in the filename, therefore i am using the list of hostnames to capture this, which becomes a problem when we go via the IP rather than the hostname
see code
hostnames = [
'HOST1',
'HOST2',
'1.1.1.1', # HOST3
'2.2.2.2', # HOST4
]
for host in hostnames:
child = pexpect.spawn('scp user#{}:/var/log/{}.backup_file0.{}.gz /home/backups/'.format(host, host))
As you can see, host1 and host 2 will connect and successfully locate the correct file as we have used the hostname, for example:
host1.backup_file0.gz
host2.backup_file0.gz
However host 3 and host 4 will fail due to the hostname in the list being an IP, however the file on these hosts is using the hostname as opposed to an IP
As a note i am not connecting to these devices via ssh so i cannot use the socket to pull the hostname
Is there any way to dynamically map these hostnames / ips and use them as needed?
I don't really see why you couldn't just match the ip with the hostname. Maybe use a dictionary:
hosts = {
'HOST1': 'HOST1',
'HOST2': 'HOST2',
'HOST3': '1.1.1.1', # HOST3
'HOST4': '2.2.2.2', # HOST4
}
for host, ip in hosts.items():
child = pexpect.spawn(f"scp user#{ip}:/var/log/{host}.backup_file0.{date}.gz /home/backups/")
Edit, if I understand correctly you added that you do not have the hostname of hosts for which you connect via IP.
Maybe just try globbing then, as each host surely only backs itself up?
for host in hostnames:
child = pexpect.spawn(f"scp user#{host}:/var/log/*.backup_file0.{date}.gz /home/backups/")

Getting 127.0.1.1 instead of 192.168.1.* ip ubuntu python

I am new to python. I want to get the ipaddress of the system. I am connected in LAN. When i use the below code to get the ip, it shows 127.0.1.1 instead of 192.168.1.32. Why it is not showing the LAN ip. Then how can i get my LAN ip. Every tutorials shows this way only. I also checked via connecting with mobile hotspot. Eventhough, it shows the same.
import socket
hostname = socket.gethostname()
IPAddr = socket.gethostbyname(hostname)
print("Your Computer Name is:" + hostname)
print("Your Computer IP Address is:" + IPAddr)
Output:
Your Computer Name is:smackcoders
Your Computer IP Address is:127.0.1.1
Required Output:
Your Computer Name is:smackcoders
Your Computer IP Address is:192.168.1.32
I got this same problem with my raspi.
host_name = socket.gethostname()`
host_addr = socket.gethostbyname(host_name)
and now if i print host_addr, it will print 127.0.1.1.
So i foundthis: https://www.raspberrypi.org/forums/viewtopic.php?t=188615#p1187999
host_addr = socket.gethostbyname(host_name + ".local")
and it worked.
As per the above '/etc/hosts' file content, you have an IP address mapping with '127.0.1.1' to your hostname. This is causing the name resolution to get 127.0.1.1. You can try removing/commenting this line and rerun.
How can I get the IP address of eth0 in Python?
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print s.getsockname()[0]
This also worked for me:
gethostbyname(gethostname()+'.')
i get the same problem what your are facing. but I get the solution with help of my own idea, And don't worry it is simple to use.
if you familiar to linux you should heard the ifconfig command which return the informations about the network interfaces, and also you should understand about grep command which filter the lines which consist specified words
now just open the terminal and type
ifconfig | grep 255.255.255.0
and hit enter now you will get wlan inet address line alone like below
inet 192.168.43.248 netmask 255.255.255.0 broadcast 192.168.43.255
in your terminal
in your python script just insert
#!/usr/bin/env python
import subprocess
cmd = "ifconfig | grep 255.255.255.0"
inet = subprocess.check_output(cmd, shell = True)
inet = wlan.decode("utf-8")
inet = wlan.split(" ")
inet_addr = inet[inet.index("inet")+1]
print(inet_addr)
this script return your local ip address, this script works for me and I hope this will work for your linux machine
all the best
This solution works for me on Windows. If you're using Linux you could try this line of code instead:
IPAddr = socket.gethostbyname(socket.getfqdn())

pyshark to capture and parse packets in remote server

Can we use pyshark module to capture/parse packets in remote server ?
Found it working in local interface :
>>> import pyshark
>>> capture = pyshark.LiveCapture(interface='eth2')
>>> capture.sniff(timeout=50)
>>> capture
<LiveCapture (4 packets)>
>>>
>>> capture[3]
<CDP Packet>
>>>
>>> print capture[3]
Packet (Length: 272)
Layer ETH:
Destination: CDP/VTP/DTP/PAgP/UDLD (01:00:0c:cc:cc:cc)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Length: 258
Address: Cisco_36:59:eb (6c:9c:ed:36:59:eb)
Same needs to be done for remote server (giving IP and few more filters)
You could do this by running the rpcapd service on the remote computer (included with WinPcap on Windows, note that you must use null authentication with the flag -n) and then running pyshark with the full URL of the remote service:
pyshark.LiveCapture(interface='rpcapd://[1.2.3.4]:2002/eth2')
Filters can always be supplied with pyshark.LiveCapture(bpf_filter='tcp')
EDIT: I added a pyshark.RemoteCapture class which is just a shortcut for the above. You can see it in the GitHub repo

Receiving multicast data on specific interface

tcmpdump can view all the multicast traffic to specific group and port on eth2, but my Python program cannot. The Python program, running on Ubuntu 12.04:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Multicast port is 52122
sock.bind(('', 52122))
# Interface eth2 IP is 1.2.3.4, multicast group is 6.7.8.9
mreq = socket.inet_aton('6.7.8.9')+socket.inet_aton('1.2.3.4')
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
print '\nwaiting to receive message'
data, address = sock.recvfrom(1024)
print data
When I use another program to send a multicast packet to eth2, it works and prints the packet. But it fails to see all the current multicast traffic. If I run tcpdump on eth2 on the same port and group as the above program:
sudo tcpdump -i eth2 host 6.7.8.9 and port 52122
it sees both the packets I send from another program AND all the current multicast traffic. It's output looks likes this...
# Packet sent from my other program
09:52:51.952714 IP 1.2.3.4.57940 > 6.7.8.9.52122: UDP, length 19
# Packet send from the outside world
09:52:52.143339 IP 9.9.9.9.39295 > 6.7.8.9.52122: UDP, length 62
Why can't my program see the packets from the outside world? How can I modify it (or something else) to fix this?
Edit:
I should have mentioned, the interface this going over is not eth2 but eth2.200 a VLAN. (The local IP and the tcpdump commands are all run with eth2.200, I just changed that in this question to make it simpler.) Based on this answer that could be the problem?
Edit #2:
netstat -ng when the program is running shows eth2.200 subscribed to 224.0.0.1 and 6.7.8.9`.
tshark -i eth2.200 igmp shows three repeated 1.2.3.4 -> 6.7.8.9 IGMP 46 V2 Membership Report / Join group 6.7.8.9 when the program first starts. When the program process is killed, it shows 1.2.3.4 -> 224.0.0.2 IGMP 46 V2 Leave group 6.7.8.9. There is also an infrequent 1.2.3.1 -> 224.0.0.1 IGMP 60 V2 Membership Query, general, where 1.2.3.1 is 1.2.3.4's gateway.
Not sure if it will help, but the routing table looks like:
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 1.2.5.6 0.0.0.0 UG 0 0 0 eth1
1.2.3.0 0.0.0.0 255.255.255.240 U 0 0 0 eth2.200
Thank you!
Finally! Found this question on ServerFault that addresses the same thing. Basically the kernel was not forwarding on / was filtering out the packets because it thought the sourced address was spoofed.
Changed the settings in /etc/sysctl.conf to match:
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_forward = 1
Rebooted and everything works.

Categories