converting IP ranges into discrete ip numbers using bash/awk/sed - sed

I am processing IP source/destination/port lists created as acl requests
The request looks some thing like this:
source IP destination IP Port
76.211.12.9 10.112.12.232 1521
The Source and destination IP's have three distinct formats
x.x.x.x,y,z
x.x.x.x-z
x.x.x.x,y.y.y.y,z,z,z,z
I want to create output
x.x.x.x
x.x.x.y
x.x.x.z
x.x.x.x
x.x.x.y
x.x.x.z
x.x.x.x
y.y.y.y
z.z.z.z
using bash, sed ,awk how can I accomplish this?
in my example:
76.211.12.9,10,11 10.112.12.232 1521
76.211.12.9-11 10.112.12.232 1521
Both outputs would look like this:
76.211.12.9 10.112.12.232 1521
76.211.12.10 10.112.12.232 1521
76.211.12.11 10.112.12.232 1521

BEGIN { DEBUG = 0 }
function setup(first_split, second_split) {
src = $1; dst = $2; port = $3
j = split(src, src_a, first_split)
k = split(src_a[4], src_a_2, second_split)
if(DEBUG)
print "<" first_split second_split ">", j, k, "\n" src
}
/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*,[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/ {
setup(",", ",")
for(i = 1; i <= j; ++i)
print src_a[i], dst, port
next
}
/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*,[0-9][0-9]*[ ,]/ {
setup(".", ",")
for(i = 1; i <= k; ++i)
print src_a[1] "." src_a[2]"." src_a[3] "." src_a_2[i], dst, port
next
}
/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*-/ {
setup(".", "-")
for(i = src_a_2[1]; i <= src_a_2[2]; ++i)
print src_a[1] "." src_a[2] "." src_a[3] "." i, dst, port
next
}
{ print }
My test file:
76.211.77.7 10.112.12.232 1521
76.211.77.8 10.112.12.232 1521
76.211.77.9,10,11 10.112.12.232 1521
76.211.77.12-13 10.112.12.232 1521
76.211.77.14,76.211.77.15,76.211.77.16 10.112.12.232 1521
This script will work in the One True Awk and also with gawk.

In order to generalize the awk solution from my other answer to all three fields, I think we would end up using awk simply as a general purpose programming language.
Now, awk is wonderful, and in the mid-1970's when Unix appeared, well, it was a collective software Renaissance. But advanced languages have joined the Unix software tools club as well, and really, I would rather write it in Ruby...
Ruby this time, see my other answer for an Awk approach...
class IPMacro
private_class_method :new
def self.get_base a
##root = a[0].split('.').tap { |x| ##last = x[3] || x[0] }.take(3).join('.')
end
def self.expand_last_comma a
self.get_base a
[a[0], *(a.drop(1).map { |e| [##root, e].join('.') })]
end
def self.expand_last_dash a
self.get_base a
##root = ##root['.'] ? [##root] : []
[*(##last..a[1]).to_a.map do |e|
(##root + [String(e)]).join '.'
end
]
end
def self.expand f
a = f.split ','
if a[1]
return self.expand_last_comma a unless a[1]['.'] || !a[0]['.']
else
a = f.split '-'
return self.expand_last_dash a if a[1]
end
return [*a]
end
def self.run
$<.each_line do |line|
a = line.split(' ').map do |f|
self.expand f
end
a[0].each do |a1|
a[1].each do |a2|
a[2].each do |a3|
puts '%s %s %s' % [a1, a2, a3]
end
end
end
end
end
self
end.run
My test case this time was...
76.211.77.5 10.112.12.227 1400,1401,1402
76.211.77.6 10.112.12.228-231 1510-1515
76.211.77.7 10.112.12.232 1521
76.211.77.8 10.112.12.232 1521
76.211.77.9,10,11 10.112.12.232 1521
76.211.77.12-13 10.112.12.232 1521
76.211.77.14,76.211.77.15,76.211.77.16 10.112.12.232 1521

Expletive deleted dude!
This is some sweet code.
Very elegant..
It's exactly what I needed. I ran it against my 340 lines of data and generated over 7500 individual src/dest/port pairs.
Thanks

Related

Most simple network protocol for a remote function call?

I am looking for the most simple protocol to program a remote function call, e.g. from Matlab to Julia.
[out1, out2, ...] = jlcall(socket, fname, arg1, arg2, ...);
fname is a string, all other input and output variables are numerical arrays (or other structures known to both sides) on Linux, Windows as option.
Client: open connection, block, pack and transmit
Server: receive, unpack, process, pack and transmit back
Client: receive, unpack, close connection and continue
The solutions I've seen (tcp, zmq) were built with old versions and do no longer work.
Protocol could (should?) be limited to do the pack/transmit - receive/unpack work.
UPDATE
Here is what I have come up with using pipes:
function result = jlcall(varargin)
% result = jlcall('fname', arg1, arg2, ...)
% call a Julia function with arguments from Matlab
if nargin == 0 % demo
task = {'foo', 2, 3}; % demo fun, defined in jsoncall.jl
else
task = varargin;
end
% create pipe and write function and parameter(s) to pipe
pipename = tempname;
pipe = java.io.FileOutputStream(pipename);
pipe.write(uint8(jsonencode(task)));
pipe.close;
% run Julia and read result back
system(sprintf('julia jsoncall.jl %s', unixpath(pipename)))
fid = fopen(pipename, 'r');
c = fread(fid);
result = jsondecode(char(c'));
fclose(fid);
function path_unix = unixpath(path_pc)
%convert path to unix version
path_unix = path_pc;
path_unix(strfind(path_unix,'\'))='/';
# jsoncall.jl
using JSON3 # get JSON3.jl from repository first
function foo(a,b) # demo function
a+b, a*b
end
jsonfile = ARGS[1] # called as > julia jsoncall.jl <json_cmdfile>
io = open(jsonfile, "r") # open IOStream for read
data = read(io) # read UTF8 data from stream
close(io) # close stream
cmd = JSON3.read(String(data)) # unpack stream into [fun, farg] array
fun = Symbol(cmd[1]) # first element is Julia function name,
result = #eval $fun(cmd[2:end]...) # others are function arguments
io = open(jsonfile, "w") # open IOStream for write
write(io, JSON3.write(result)) # (over-)write result back to stream
close(io) # close stream
Open points:
my first use of pipes/streams
output formatting: where Julia outputs a tuple of two, Matlab creates an an nx2 array.
replace json by msgpack for performance, might help with type formatting as well.
Your comments are welcome!
Here is a stripped down way of doing it. If you are going to vary your functions and arguments, a REST as in the comments server is going to be more flexible and less likely to pose a security risk (as you are eval()ing arbitrary code in some cases).
#server code
using Sockets
const port = 6001
const addr = ip"127.0.0.1"
const server = listen(addr, port)
while true
try
#info "Server on $port awaiting request..."
sock = accept(server)
#info "Server connected."
msg = strip(readline(sock))
#info "got message $msg"
fstr, argstr = split(msg, limit=2)
x = parse(Float64, argstr) # or other taint checks here...
ans = eval(Meta.parse(fstr * "($x)"))
#info "server answer: $ans"
write(sock, "$ans\n")
catch y
#info "exiting on condition: $y"
end
end
# client code
using Sockets
port = 6001
server = ip"127.0.0.1"
sock = connect(server, port)
#info "Client connected to $server"
func = "sinpi"
x = 0.5
#info "starting send"
write(sock, "$func $x\n")
flush(sock)
#info "flushed send"
msg = strip(readline(sock)) # read one line of input and \n, remove \n
ans = parse(Float64, msg)
println("answer is $ans")
close(sock)

Python simple UDP server does not receive message with IP options

I have a simple udp server/client setup where I send a message from the client and print it on the server. This works well for a regular IP packet but the message is not received when I add an IP options header to the packet, even though I can sniff the packet using scapy.
Here's the packet without IP options
###[ Ethernet ]###
dst = 00:04:00:00:04:01
src = 00:aa:00:02:00:04
type = 0x800
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 47
id = 1
flags =
frag = 0L
ttl = 61
proto = udp
chksum = 0x62f4
src = 10.0.2.101
dst = 10.0.4.101
\options \
###[ UDP ]###
sport = 10001
dport = 3478
len = 27
chksum = 0x2bd1
###[ Raw ]###
load = 'message from a game'
And here's the packet with IP options header:
###[ Ethernet ]###
dst = 00:04:00:00:04:01
src = 00:aa:00:02:00:04
type = 0x800
###[ IP ]###
version = 4L
ihl = 8L
tos = 0x0
len = 59
id = 1
flags =
frag = 0L
ttl = 61
proto = udp
chksum = 0x5fe8
src = 10.0.2.101
dst = 10.0.4.101
\options \
|###[ IPOption ]###
| copy_flag = 1L
| optclass = control
| option = 31L
| length = 12
| value = '\x00\x01\x00\x00RTGAME'
###[ UDP ]###
sport = 10001
dport = 3478
len = 27
chksum = 0x2bd1
###[ Raw ]###
load = 'message from a game'
And here's the UDP server:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', args.port))
while True:
try:
data, addr = sock.recvfrom(1024)
print("received: %s" % data)
except KeyboardInterrupt:
sock.close()
break
I've been stuck on this for a few days and would love if someone could figure it out.
Thanks
have just been playing and the following works as a self-contained/minimal working example for me with Python 3.7.1 under both OSX and Linux
generating a valid set of IP Options:
from scapy.all import IPOption, raw
ipopts = raw(IPOption(
copy_flag=1, optclass='control', option=31,
value='\x00\x01\x00\x00RTGAME'))
(if you don't have Scapy, the above should generate: b'\x9f\x0c\x00\x01\x00\x00RTGAME')
client code:
import socket
from time import sleep
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(('127.0.0.1', 3478))
s.setsockopt(socket.IPPROTO_IP, socket.IP_OPTIONS, ipopts)
while True:
s.send(b'message from a game')
sleep(1)
server code:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind(('', 3478))
s.setsockopt(socket.IPPROTO_IP, socket.IP_RECVOPTS, 1)
while True:
print(*s.recvmsg(4096, 1024))
this should result in the "server" displaying lines like:
b'message from a game\n' [(0, 6, b'\x9f\x0c\x00\x01\x00\x00RTGAME')] 0 ('127.0.0.1', 46047)
furthermore, I can watch packets move over the network by running:
sudo tcpdump -i lo0 -vvv -n 'udp and port 3478'
at the command line, or this in Scapy:
sniff(iface='lo0', filter='udp and port 3478', prn=lambda x: x.show())
for some reason I don't actually receive the ancillary data containing the IP Options under OSX, but the data shows up in the packet sniffers.
The problem was due to an incorrect IPv4 checksum. I failed to mention in the question that I'm running this in a mininet environment with custom switches. The IP options get added in transit by a switch, but the checksum wasn't updated. Once I fixed that, the packet made it to the server.
Thanks for the help and pointers everyone!

How can I take my captured information from a network/port scan and write that to a file?

I wrote an IP and port scanning program and I want to take the captured data and output it to a text file. I've been trying to figure it out for a while and haven't had any luck applying what I can find in searches. At the end, I commented out how I thought it should work to write the information to a file.
Any help or suggestions would be greatly appreciated, I'm still somewhat new to Python and trying to learn.
#!/usr/bin/env python
import ipaddress
import sys, time
import os
import subprocess
import socket
from datetime import datetime
FNULL = open(os.devnull, 'w')
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Welcome to the IP/Port Scanner and Logger')
address = input('Enter starting IP address: ')
split1 = first,second,third,fourth = str(address).split('.')
start = int(fourth)
host = first+'.'+second+'.'+third+'.'+str(start)
end_address = input('Enter the ending IP address: ')
split2 = first,second,third,fourth = str(end_address).split('.')
end = int(fourth)
network = first+'.'+second+'.'+third+'.'
min_port = input("Enter starting port range: ")
max_port = input("Enter ending port range: ")
remoteserver = host
remoteserverIP = socket.gethostbyname(remoteserver)
def port_scan():
print ('Port scanning function initialized:')
try:
for port in range(int(min_port),int(max_port)):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((remoteserverIP, port))
if result == 0:
print ('Port ' + str(port) + ': Open')
sock.close()
except KeyboardInterrupt:
print ("You halted the process")
sys.exit()
except socket.gaierror:
print ('Hostname could not be resolved. Exiting')
sys.exit()
except socket.error:
print ("Couldn't connect to server")
sys.exit()
return port
def check_up():
for ip_address in range(int(start), int(end)):
try:
subprocess.check_call(['ping', '-c', '2',
network + str(ip_address)],
stdout=FNULL,stderr=FNULL)
except (OSError, subprocess.CalledProcessError):
print ("{}{}".format(network,ip_address), "is down")
except KeyboardInterrupt:
print ("You halted the process")
sys.exit()
else:
print ("{}{}".format(network,ip_address), "is up")
return ip_address
check_up()
time1 = datetime.now()
time2 = datetime.now()
scantime = time2-time1
print ('Scan completed in: ', scantime)
while True:
print ('Would you like to write information to file?')
answer = input()
if answer in ['yes', 'y', 'yeah']:
print ('Alright, writing to file')
print ('Program will exit upon scan completion.')
break
elif answer in ['no', 'n']:
print ('Okay, exiting now..')
sys.exit()
break
else:
print ('Please enter a yes or no value')
###Output File
##with open('ipscan.txt', 'w+') as ip:
## print (ip_address, port)
##
##sys.exit()

Incorrect throughput value in python

I am writing a python code to find throughput between server and client. It is based on speedtest.net functionality where I am sending a dummy file to calculate the speed. The problem I am facing is unreliable throughput output. I will appreciate your suggestions on the same. Here is the code.
server.py
import socket
import os
port = 60000
s = socket.socket()
host = socket.gethostname()
s.bind((host, port))
s.listen(5)
print 'Server listening....'
while True:
conn, addr = s.accept()
print 'Got connection from', addr
data = conn.recv(1024)
print('Server received', repr(data))
filename='akki.txt'
b = os.path.getsize(filename)
f = open(filename,'rb')
l = f.read(b)
while (l):
conn.send(l)
l = f.read(b)
f.close()
print('Done sending')
conn.send('Thank you for connecting')
conn.close()
Client.py
import socket
import time
import os
s = socket.socket()
host = socket.gethostname()
port = 60000
t1 = time.time()
s.connect((host, port))
s.send("Hello server!")
with open('received_file', 'wb') as f:
print 'file opened'
t2 = time.time()
while True:
data = s.recv(1024)
if not data:
break
f.write(data)
t3 = time.time()
print data
print 'Total:', t3 - t1
print 'Throughput:', round((1024.0 * 0.001) / (t3 - t1), 3),
print 'K/sec.'
f.close()
print('Successfully received the file')
s.close()
print('connection closed')
Output when sending akki.txt
Server Output
Server listening....
Got connection from ('10.143.47.165', 60902)
('Server received', "'Hello server!'")
Done sending
Client output
file opened
Raw timers: 1503350568.11 1503350568.11 1503350568.11
Total: 0.00499987602234
**Throughput: 204.805 K/sec.**
Successfully received the file
connection closed
Output for ak.zip ( which is bigger file)
Client output
file opened
Total: 0.0499999523163
**Throughput: 20.48 K/sec.**
Successfully received the file
connection closed
Short Answer: you need to take the file size into consideration.
More Details:
Throughput is data/time. Your calculation:
round((1024.0 * 0.001) / (t3 - t1), 3)
Doesn't take the file size into account. Since sending a large file takes more time, 't3-t1' is bigger so your throughput is smaller (same numerator with larger denominator). Try adding the file size to the formula and you should get much more constant results.
Hope this helps.

import ip address in octave

I have a dataset that consists of IP addresses packets transferred etc. Octave is converting the IP addresses into float values. How do I import IP addresses as it is and what data type is to be used (String?)?
How do you import them in octave? GNU Octave has plenty of functions to load/save data. It depends how your IP adresses (IPv4 or IPv6?) are stored in your file which function is the easiest/best for you.
For example if you have a file called "ips.txt".
192.168.10.4
8.8.8.8
14.32.244.8
You could use this to get a cell:
octave:1> f = fopen("ips.txt", "r");
octave:2> l = textscan(f, "%s");
octave:3> fclose(f);
octave:4>
octave:4> l{1}
ans =
{
[1,1] = 192.168.10.4
[2,1] = 8.8.8.8
[3,1] = 14.32.244.8
}
octave:5>
But perhaps char(fread(..)) or fgetl may be better for you dependent what you want to do later with the imported ips...
addition:
Because you commented that you have IP addresses are inside a list of floats and not a fixed scheme (a fixed scheme would be for example: "The wanted ips are at the beginning of the line, the 4.th column or somethink like that which could be processed with awk) I also add a possibility with regexp:
I created this file ips.txt:
192.168.10.4 some text 3.14 8.8.8.8
other 123.44 14.32.244.8
4.667.2 12.943 127.0.0.1 hello world
And load it with this script using regexp
f = fopen("ips.txt", "r");
x = char(fread(f));
fclose(f);
[S, E, TE, M, T, NM, SP] = regexp (x', '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}');
which gives you for M:
M =
{
[1,1] = 192.168.10.4
[1,2] = 8.8.8.8
[1,3] = 14.32.244.8
[1,4] = 127.0.0.1
}
-- Andy