Script with network settings - ip

Hey there I want to write a script that will change the network profile settings (ifconfig, /etc/resolv.comf). Let the script retrieve and display the contents of the file with network profiles to root. The format of the database file will be in the form of: IP, IP Mask, Gateway. I've already done something but don't know if it's correct.
#!/bin/bash
IP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
IPMask=$(/sbin/ifconfig eth0 | grep Mask | cut -d":" -f4)
Gateway=$(/sbin/ip route | awk '/default/ {print $3}')
echo "IP is : $IP"
echo "IP Mask is: $IPMask"
echo Gateway is: $Gateway"
The part I don't understand how to do is - Root interactively selects the network profile (by number), which is then activated. Any help please?

Related

Extract TCP payload from pcap file

Using tcpdump, I am capturing network traffic. I am interested in extracting the actual TCP payload data, i.e. HTTP traffic in my particular case.
I tried to achieve that using scapy, but I only found function remove_payload(). Is there a corresponding counterpart? Or do you know of any other tools that provide such functionality?
Unfortunately, I did not find a satisfactory scapy documentation.
You can read a pcap with Scapy easily with rdpcap, you can then use the Raw (right above TCP) layer of your packets to play with HTTP content:
from scapy.all import *
pcap = rdpcap("my_file.pcap")
for pkt in pcap:
if Raw in pkt:
print pkt[Raw]
In case other users might have similar questions: I ended up using the following script:
infile=infile.pcap
outfile=outfile
ext=txt
rm -f ${outfile}_all.${ext}
for stream in $(tshark -nlr $infile -Y tcp.flags.syn==1 -T fields -e tcp.stream | sort -n | uniq | sed 's/\r//')
do
echo "Processing stream $stream: ${outfile}_${stream}.${ext}"
tshark -nlr $infile -qz "follow,tcp,raw,$stream" | tail -n +7 | sed 's/^\s\+//g' | xxd -r -p | tee ${outfile}_${stream}.${ext} >> ${outfile}_all.${ext}
done

Find out which network interface belongs to docker container

Docker creates these virtual ethernet interfaces veth[UNIQUE ID] listed in ifconfig. How can I find out which interface belongs to a specific docker container?
I want to listen to the tcp traffic.
To locate interface
In my case getting value from container was like (check eth0 to):
$ docker exec -it my-container cat /sys/class/net/eth1/iflink
123
And then:
$ ip ad | grep 123
123: vethd3234u4#if122: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
Check with tcpdump -i vethd3234u4
Reference about mysterious iflink from http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-class-net:
150 What: /sys/class/net/<iface>/iflink
151 Date: April 2005
152 KernelVersion: 2.6.12
153 Contact: netdev#vger.kernel.org
154 Description:
155 Indicates the system-wide interface unique index identifier a
156 the interface is linked to. Format is decimal. This attribute is
157 used to resolve interfaces chaining, linking and stacking.
158 Physical interfaces have the same 'ifindex' and 'iflink' values.
Based on the provided answer (which worked for me), I made this simple bash script:
#!/bin/bash
export containers=$(sudo docker ps --format "{{.ID}}|{{.Names}}")
export interfaces=$(sudo ip ad);
for x in $containers
do
export name=$(echo "$x" |cut -d '|' -f 2);
export id=$(echo "$x"|cut -d '|' -f 1)
export ifaceNum="$(echo $(sudo docker exec -it "$id" cat /sys/class/net/eth0/iflink) | sed s/[^0-9]*//g):"
export ifaceStr=$( echo "$interfaces" | grep $ifaceNum | cut -d ':' -f 2 | cut -d '#' -f 1);
echo -e "$name: $ifaceStr";
done
My answer more like improvement on that important topic because it didn't help to "Find out which network interface belongs to docker container", but, as author noticed, he "want to listen to the tcp traffic" inside docker container - I'll try to help on that one during your troubleshooting of network.
Considering that veth network devices are about network namespaces, it is useful to know that we can execute program in another namespace via nsenter tool as follow (remember - you need a privileged permission (sudo/root) for doing that):
Get ID of any container you are interested in capture the traffic, for example it will be 78334270b8f8
Then we need to take PID of that containerized application (I assume you are running only 1 network-related process inside container and want to capture its traffic. Otherwise, that approach is hard to be suitable):
sudo docker inspect 78334270b8f8 | grep -i pid
For example, output for pid will be 111380 - that's ID of your containerized app, you can check also it via ps command: ps aux | grep 111380 just in curiosity.
Next step is to check what network interfaces you have inside your container:
sudo nsenter -t 111380 -n ifconfig
This command will return you list of network devices in network namespace of the containerized app (you should not have ifconfig tool on board of your container, only on your node/machine)
For example, you need to capture traffic on interface eth2 and filter it to tcp destination port 80 (it may vary of course) with this command:
sudo nsenter -t 111380 -n tcpdump -nni eth2 -w nginx_tcpdump_test.pcap 'tcp dst port 80'
Remember, that in this case you do not need tcpdump tool to be installed inside your container.
Then, after capturing packets, .pcap file will be available on your machine/node and to read it use any tool you prefer tcpdump -r nginx_tcpdump_test.pcap
approach's pros:
no need to have network tools inside container, only on docker node
no need to search for map between network devices in container and node
cons:
you need to have privileged user on node/machine to run nsenter tool
One-liner of the solution from #pbaranski
num=$(docker exec -i my-container cat /sys/class/net/eth0/iflink | tr -d '\r'); ip ad | grep -oE "^${num}: veth[^#]+" | awk '{print $2}'
If you need to find out on a container that does not include cat then try this tool: https://github.com/micahculpepper/dockerveth
You can also read the interface names via /proc/PID/net/igmp like (container name as argument 1):
#!/bin/bash
NAME=$1
PID=$(docker inspect $NAME --format "{{.State.Pid}}")
while read iface id; do
[[ "$iface" == lo ]] && continue
veth=$(ip -br addr | sed -nre "s/(veth.*)#if$id.*/\1/p")
echo -e "$NAME\t$iface\t$veth"
done < <(</proc/$PID/net/igmp awk '/^[0-9]+/{print $2 " " $1;}')

How to bind rsync to a specific interface?

I have a lot of interfaces configured in my server, each of which connect to a specific nic card and have a separate routing table. These interfaces can be identified by "netstat -a" command.
Now, I want to execute the rsync command connecting only to specific interface. I have this requirement because each of the interfaces will go through a separate tunnel/path and I want a particular rsync command to sync files through a specified tunnel.
Specifically, I want a way to specify the interface name.
Thanks,
Mohan.
You can specify the address of the interface using --address=x.x.x.x on the command-line.
I don't think there is any way to specify the interface directly, but the ip command can tell you the address for an interface, so you could use something like this:
IP=$(ip -4 -br addr show eth0 | awk '{split($3,a,"/"); print a[1]}')
rsyncd ... --address=$IP
Edit For systems with the "real" iproute2 (anything not busybox-based, essentially), ip can produce JSON output which can be parsed a bit more sanely:
IP=$(ip -j -4 addr show wlo1 | jq .[0].addr_info[0].local)
rsyncd ... --address=$IP
I've written this little perl script to turn interface names to addresses, save it as iftoip (or similar)
#!/usr/bin/perl
use strict;
use warnings;
use IO::Interface::Simple;
use feature qw(say);
my $iface = shift;
my $if = IO::Interface::Simple->new($iface) or die "$!: $iface";
say $if->address;
exit 0;
You can do something similar with bash:
iftoip() {
ip addr show $1 | grep inet | awk '{print $2}' | cut -d'/' -f1
}
just add the above 3 lines to ~/.bashrc and start a new shell or source ~/.bashrc
Running it produces:
v#juno:~$ iftoip ens33
10.251.17.94
v#juno:~$ iftoip ens34
192.168.78.128
v#juno:~$ echo "IP=$(iftoip ens33)"
IP=10.251.17.94
v#juno:~$ iftoip ens35 #perl
No such device: ens35 at /home/v/bin/iftoip line 10.
or
v#juno:~$ iftoip ens35 #bash
Device "ens35" does not exist.
This has been tried using 2 interfaces, with different subnets and worked.
rsync -avzP -e 'ssh -b 10.100.16.X' /var/tmp/ent1 10.100.16.X:/var/tmp/;
rsync -avzP -e 'ssh -b 10.100.20.X' /var/tmp/ent2 10.100.20.X:/var/tmp/ ;
From client to server, over ssh use:
rsync -avP -e 'ssh -b x.x.x.x' tmp/ server:tmp/

Passing Local IP as argument when running command line application in Unix

I have a command line application which I use and also have to pass my local ip address as an argument, like:
jekyll --url 'http://192.168.1.2:3000' --pygments --safe --server 3000 --auto
I would like to make the url argument get my ip automatically, since I am always on different networks and get different loal ip addresses.
so I can use this alias in my .bashrc
alias jkl="jekyll --url 'http://$IP:3000' --pygments --safe --server 3000 --auto"
where $IP would be my local ip adress acquired dynamically.
Is there any way to do it?
First, use double quotes instead of single quotes around your $IP variable or else it won't interpolate the value
#!/bin/bash
# tested on bash 4
while read -r line
do
case "$line" in
"inet "* )
line="${line/inet /}"
line="${line%% *}"
if [[ ! $line =~ ^(127|172) ]] ;then
IP="$line"
echo "IP: $IP"
fi
;;
esac
done < <(ifconfig)
echo jekyll --url "http://$IP:3000" --pygments --safe --server 3000 --auto
Note that you will have a few different IPs in the output. Choose the one that fits your requirement most.
A computer does not necessarily have "a local IP address", there are often several. For instance, you typically have the localhost address (127.0.0.1), and one or more "true" externally visible addresses. It's hard for an automated solution to know which one to pick.
One easy solution is perhaps to hard-code the "eth0" interface (or whatever the name is of your most typical interface).
On Linux, you could use something like this:
$ ifconfig | grep -A1 eth0 | cut -d: -f2 | cut -d ' ' -f1 | grep \\.
192.168.0.8
So to stuff this into a variable (assuming bash) you would use
MY_IP=$(ifconfig | grep -A1 eth0 | cut -d: -f2 | cut -d ' ' -f1 | grep \\.)
Note that this hard-codes the interface name as eth0.

Increase the performace of the code by reducing the number of ssh

This function take hugh amount of time to calculate the status of a process, beacuse every time it has to ssh into the machine and find the status of a process.
I only have four machines and around 50+ process to monitor and the details are mentioned into configDaemonDetails.txt
like:
abc#sn123|Daemon_1|processname_1
abc#sn123|Daemon_2|processname_2
efg#sn321|Daemon_3|processname_3
How to reduce the time with doing ssh once into a machine and finding all its process informations as defined in the txt file. ?
CheckProcessStatus ()
{
echo " ***** Checking Process Status ***** "
echo "========================================================="
IFS='|'
cat configDaemonDetails.txt | grep -v "^#" | while read MachineDetail Daemon ProcessName
do
Status=`ssh -f -T ${MachineDetail} ps -ef | egrep -v "grep|less|vi|more" | grep "$ProcessName"`
RunTime=`echo "$Status" | sed -e 1'p' -e '1,$d' | awk '{print $5" "$6}'`
if [ -z "$Status" ]
then
echo "The Process is DOWN $Daemon | $ProcessName "
else
echo "The Process $Daemon | $ProcessName is up since $RunTime"
fi
done
echo "-----------------------------------------------------"
}
Thanks :)
Can't you just fetch the entire ps -ef output at once, and then parse it appropriately? I suspect that is what you are asking, and maybe all you want is an example of how to do that? If that is the case, say so and I'll flesh out an example.
SSH is a bit over kill for getting status of a process, I'd suggest using SNMP instead.
e.g, you can get a process list like this:
snmpwalk -v2c -cPASSWORD HOST 1.3.6.1.2.1.25.4.2.1
Take a look at this Nagios plugin that does process checks, and look in the code for the actual SNMP OIDs.

Resources