Get bytes count using iptables when having a Docker host - docker

When I want to count the number of bytes getting out a Linux system through a particular port I can use iptables, adding a specific rule that can be checked whenever I need.
For instance lets imagine that I need to know how many bytes go out through port 22. I can add the following rule:
iptables -A OUTPUT -p tcp --sport 22
And when I need to know the answer to my question, I run:
iptables -L -nvx
Or if I need just the bytes:
iptables -L -nvx | grep :22 | awk '{ print $2 }'
My problem is that if that system is running Docker, the iptables are changed as explained here and I can't get the desired effect (if I repeat the process above I always get 0 bytes even knowing that was traffic on that port).
Can someone please explain how can I obtain the same bytes count in this case?

Related

Can't parse tcpdump output correctly

I'm trying to run this command: sudo tcpdump "ether proto 0x888e and ether host <BSSID>" -I -w -U -vvv -I <INTERFACENAME> -w ~/Desktop/handshake.cap which works perfectly in terms of its function, however, when I run the command, I get the following output:
tcpdump: listening on en0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), capture size 262144 bytes
Got 0
Where Got 0 counts the number of packets captured. Furthermore when stopping the command, I get the following:
tcpdump: listening on en0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), capture size 262144 bytes
^C0 packets captured
3526 packets received by filter
0 packets dropped by kernel
I'm trying to integrate this command into a script and would simply like everything but Got 0 to be omitted from the output.
I have experienced this sort of problem before but have simply used 2> /dev/null to get rid of the output I don't want. However, it seems that Got 0 is included in this blocked output and as a result, I get no output at all. Similarly, &>/dev/null removes all output as well. I have also tried piping it to sed -n '1!p' to ignore the first line but this has no effect and would not be preferable because in theory it would not remove 0 packets captured
3526 packets received by filter
0 packets dropped by kernel
Is anyone aware of how to resolve this issue?
Thank you in advance for any help,
Kind regards, Rocco
P.S. I am running macOS

How to limit bandwidth to a set of hosts

I'd like to limit bandwidth to a set of local hosts by adding an appropriate config to my router.
IIUC I can limit the bandwidth like I want with:
tc qdisc add dev $IF root tbf burst 1mb rate 100kbps
Except that this affects all machines connected to $IF, whereas I only want some of them to be affected. I figured that I can tag the relevant packets with something like:
iptables -t mangle -A POSTROUTING -j CLASSIFY \
--dst 192.168.1.128/25 --set-class 1:10
However, the missing part I can't figure out is which classful scheduler to use on $IF, and how to add a tbf queue for those packets of the 1:10 class.
[ BTW, I see someone voted to close this question. Any idea why? Would there be a better place to ask such questions? ]

How to add a docker health check to test a tcp port is open?

I have a server which is running an apache hive service on port 9083. The thing is it doesn't support http protocol (but uses thrift protocol).so I can't simply add
HEALTHCHECK CMD http://127.0.0.1:9083 || exit 1 # this check fails
All I want is to check if that port is open. I have netstat and curl on server but not nc.
So far I tried the below options, but none of them is suitable as a health check.
netstat -an | grep 9083 | grep LISTEN | echo $? # This works
netstat -an | grep 9084 | grep LISTEN | echo $? # but so does this
The problem as I interpret from the above is it's simply telling me my syntax is correct, but not really testing if that port is really listening
because when I do netstat -an I get the following output,which clearly shows only 9083 is listening but not 9084
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0
0.0.0.0:9083 0.0.0.0:* LISTEN tcp 0 0
Though answering an old question, for future googlers, the following worked for me:
HEALTHCHECK CMD netstat -an | grep 9083 > /dev/null; if [ 0 != $? ]; then exit 1; fi;
The shorter version of it:
netstat -ltn | grep -c 9083
Used options:
netstat:
-l - display listening server sockets
-t - display TCP sockets only
-n - don't resolve names
grep
-c - returns a number of founded lines, but it also gives a useful exit code; 0 if found, 1 if not found
You can use /dev/tcp
Like this :
printf "GET / HTTP/1.1\n\n" > /dev/tcp/127.0.0.1/9083
For more information, you can check this : http://www.tldp.org/LDP/abs/html/devref1.html#DEVTCP
Piotr Perzynas answer is quite good, but it will also return 0 if thereā€˜s a port like 19083 because it finds the substring 9083 in that line.
a better check would be:
netstat -ltn | grep -c ":9083"
I really loved Wassim Dhif answer. Mostly because it does not depend on netstat.
Netstat was obsolete before the question was asked.
From netstat's manpage:
Note
This program is obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i is ip -s link. Replacement for netstat -g is ip maddr.
And you need netstat (or ss) installed in the container. You only want to check if a port is open. Wassim Dhif's answer just needs bash (and yes, not every image has it). In my experience, you usually want the image as light as possible.
In my compose I used it as follows:
healthcheck:
test: "bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/8080; exit $?;'"
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
Note that the string test is equivalent to specifying CMD-SHELL followed by that string (from the Compose Specification

iperf, sctp command not recognized in command-promt

I'm using iperf3 that is supposedly a rewritten version of iperf. Reason why Im using this is because I love iperf when it comes to TCP and UDP throughput and I now want to test SCTP throughput between my end-points.
However when I'm trying to use the --sctp command that I've seen people been using it says command not recognizable. Is it the implementation I'm using that have not implemented this command?
https://github.com/esnet/iperf
This is the implementation I'm using, can't find any obvious documentation of the SCTP commands related to this. Most SCTP iperf implementations are added manually in the tests and the source code is often not provided.
Any help would be appreciated!
Get a copy of iperf which supports lksctp module of linux kernel. Install it using the standard process. (If it fails, please inform with the error message and the operating system and kernel details). Now to use SCTP in iperf these are the proper syntaxes.
For creating an SCTP server,
iperf -z -s
(-z is for selecting the SCTP protocol and -s is for server.)
For creating an SCTP client,
iperf -z -c <host address> -t <time duration for the connection in second>s -i <interval of the time to print the bandwidth in terminal in second>s
(-z for SCTP, -c is for client. Host address should be the ip address of the server where iperf -z -s is already running. -t is to specify the communication time duration. -i is to specify the interval to show the bandwidth.)
Example:
iperf -z -c 0.0.0.0 -t 10s -i 2s
Here the communication time is 10 seconds and it'll report the bandwidth for each 2 seconds interval.
P.S.
(1) To use iperf for SCTP, you must enable the SCTP module in the kernel and recompile it. The kernel version must be 2.6 or above. Check it using uname -a or uname -r. If you have a lower one, then download a new kernel from The Linux Kernel Archives. And compile it by enabling SCTP.
First check if it is already enabled or not by running these two commands in the terminal.
modprobe sctp
lsmod | grep sctp If you get any output then SCTP is already enabled.
(2) If still iperf with -z fails. Try the following solution. If the two machines are 'A' and 'B'.
First make 'A' the server and 'B' the client. It won't succeed. So
exit by using `ctrl + z` and kill iperf
using `pkill -9 iperf`.
Then make 'B' the server and 'A' the client. It may succeed. If it fails again, kill iperf using the above command and repeat step 1 again. it might get succeeded.
(The 2nd solution works for me with fedora 20 and kernel 2.6 and above.)
Couldn't find any recent answers through googling so I though I would leave an answer here for those looking to installing Iperf3 to use SCTP on RHEL / CentOS.
You'll need to install lksctp-tools-devel first and build from source to enable the SCTP support. Yum Install Iperf3 3.17 with lksctp-tools-devel did not enable SCTP for me.

Inform me when site (server) is online again

When I ping one site it returns "Request timed out". I want to make little program that will inform me (sound beep or something like that) when this server is online again. No matter in which language. I think it should be very simple script with a several lines of code. So how to write it?
Some implementations of ping allow you to specify conditions for exiting after receipt of packets:
On Mac OS X, use ping -a -o $the_host
ping will keep trying (by default)
-a means beep when a packet is received
-o means exit when a packet is received
On Linux (Ubuntu at least), use ping -a -c 1 -w inf $the_host
-a means beep when a packet is received
-c 1 specifies the number of packets to send before exit (in this case 1)
-w inf specifies the deadline for when ping exits no matter what (in this case Infinite)
when -c and -w are used together, -c becomes number of packets received before exit
Either can be chained to perform your next command, e.g. to ssh into the server as soon as it comes up (with a gap between to allow sshd to actually start up):
# ping -a -o $the_host && sleep 3 && ssh $the_host
Don't forget the notify sound like echo"^G"! Just to be different - here's Windows batch:
C:\> more pingnotify.bat
:AGAIN
ping -n 1 %1%
IF ERRORLEVEL 1 GOTO AGAIN
sndrec32 /play /close "C:\Windows\Media\Notify.wav"
C:\> pingnotify.bat localhost
:)
One way is to run ping is a loop, e.g.
while ! ping -c 1 host; do sleep 1; done
(You can redirect the output to /dev/null if you want to keep it quiet.)
On some systems, such as Mac OS X, ping may also have the options -a -o (as per another answer) available which will cause it to keep pinging until a response is received. However, the ping on many (most?) Linux systems does not have the -o option and the kind of equivalent -c 1 -w 0 still exits if the network returns an error.
Edit: If the host does not respond to ping or you need to check the availability of service on a certain port, you can use netcat in the zero I/O mode:
while ! nc -w 5 -z host port; do sleep 1; done
The -w 5 specifies a 5 second timeout for each individual attempt. Note that with netcat you can even list multiple ports (or port ranges) to scan when some of them becomes available.
Edit 2: The loops shown above keep trying until the host (or port) is reached. Add your alert command after them, e.g. beep or pop-up a window.

Resources