Obtaining allowed MTU range for specific device from bash-script - linux

How can one obtain MTU range supported by some network device in Linux from bash-script (not directly through netlink API)?
I tried to play with ifconfig and ip link but can't find the solution.

Package iproute2 (since v4.19) parses min/max mtu details and prints it to console when "--details" option is provided by user
ip --details link
ip --details link --name=eth0
ip --details addr
ip --details addr show dev eth0
example of script
#!/bin/bash
for nic in eth0 eth1 eth2; do
min_mtu=`ip --details link show $nic | grep 'minmtu'| sed -r 's/^(.*minmtu) ([0-9]+) (.*)$/\2/'`
max_mtu=`ip --details link show $nic | grep 'maxmtu'| sed -r 's/^(.*maxmtu) ([0-9]+) (.*)$/\2/'`
echo "$nic - min: $min_mtu, max: $max_mtu"
done
output:
eth0 - min: 60, max: 9000
eth1 - min: 68, max: 1770
eth2 - min: 68, max: 1770
Debian 10 already has recent enough version of iproute2 package (v4.20) to display min/max mtu.
Ubuntu 18.04.3 has a kernel which already provides this information to userspace but iproute2 package is not fresh enough(v4.15) to parse kernel's data (and display them to the user).
You can build fresh iproute2 tools yourself in case you have outdated package.
git clone git://git.kernel.org/pub/scm/network/iproute2/iproute2.git
cd iproute2 && ./configure && make && ./ip/ip --details link

Related

Check NetworkManager is DHCP or Static with command line Ubuntu

How can I check the GUI network setting is set DHCP or Static with command line? for the active and connected interface in Ubuntu 18.04
I want one line command like grep give me static/dhcp or true/false
Can use ip command to check interface you're interested in.
E.g. to check the interface eth0:
if ip -6 addr show eth0 | grep -q dynamic; then
echo "Uses DHCP addressing"
else
echo "Uses static addressing"
fi
-6 option is for checking IPv6 interface. You can use -4 for IPv4.
nmcli -f ipv4.method con show
If the output is auto, then it is DHCP.
If the output is manual, then it is static.
or
cat /etc/network/interfaces
DHCP enabled
auto eth0
iface eth0 inet dhcp

How to get bridge support with /etc/network/interfaces?

There are some linux distros, where it is possible to configure a bridge in /etc/network/interfaces. As explained for example here, it is enough to use this to form a bridge:
iface eth0 inet manual
iface eth1 inet manual
iface br0 inet dhcp
bridge_ports eth0 eth1
I am building a custom linux image using yocto. In my image this is not working. Yocto version is morty, which is already 3 years old.
So, what I need to do to get this functionality? Is it enough to get a newer version of the ifupdown package (I assume that this package provides this functionality)?
I installed the bridge-utils package, and I could add a bridge using brctl, as explained here:
brctl addbr br0
brctl addif br0 eth0 eth1
but I do not want to do it manually. I would like to do it by modifying /etc/network/interfaces, because then the changes are saved between reboots.
Do you use systemd?
If so, try a bbappend of systemd-machine-units, e.g.:
FILESEXTRAPATHS_prepend := "${THISDIR}/systemd-machine-units:"
SRC_URI += " \
file://10-eth0.network \
file://10-eth1.network \
"
do_install_append() {
for file in $(find ${WORKDIR} -maxdepth 1 -type f -name *.network); do
install -m 0644 "$file" ${D}${systemd_unitdir}/network/
done
}

Ubuntu keeps losing resolv.conf settings?

Every time I reboot my ubuntu server, it loses it's nameserver setting. I have to run:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
each time I reboot for it to work properly again.
I tried editing resolv.conf directly and still doesn't work properly.
Any advice?
Edit below file for making effect on every time when you reboot
This is head section of resolve conf which added in resolve.conf
/etc/resolvconf/resolv.conf.d/head
In Ubuntu 18.04 thats working:
Sudo rm /etc/resolv.conf
sudo echo "nameserver xxx.xxx.xxx.xxx" >> /etc/systemd/resolve/resolv.conf
sudo ln -s /etc/systemd/resolve/resolv.conf /etc/resolv.conf
But I think a better option would be to edit the /etc/network/interfaces file and configure the system correctly, including the dns you need, for example:
auto lo
iface lo inet loopback
auto enp0s3
iface enp0s3 inet dhcp
dns-nameservers 8.8.8.8 8.8.4.4
In this example the first two lines define the local interface, do not touch it, the third line says that when the computer boots up the network card enp0s3 simultaneously (you can find out the name of your network card(s) with the command ifconfig -a), the fourth line tells the enp0s3 card to listen to a dhcp server and take the data needed for its network configuration from there, and the last line tells it which dns you want to use.
If you know your network configuration, it will always be the same or you don't have a dhcp server, the file would be something like this:
auto lo
iface lo inet loopback
auto enp0s3
iface enp0s3 inet static
address 10.10.5.67
netmask 255.255.255.0
gateway 10.10.5.1
broadcast 10.10.5.255
dns-nameservers 8.8.8.8 8.8.4.4
Another possibility is to configure the netplan file, the new default mode to manage the network from ubuntu 17.10 Artful. Here you can see more on the subject, particularly I don't like it but I am aware of its power for complex cases.
You can keep settings by editing a base file.
Install resolvconf:
sudo apt-get install resolvconf
Edit /etc/resolvconf/resolv.conf.d/base:
sudo vi /etc/resolvconf/resolv.conf.d/base
Add your nameserver:
nameserver 8.8.8.8
Start resolvconf:
sudo /etc/init.d/resolvconf start
Check that /etc/resolv.conf contains the following line:
nameserver 8.8.8.8
Then try to restart your server and check /etc/resolv.conf again.
That happens because of resolvconf. As the man page states, it allows other programs to change the DNS resolver configuration. Probably, there is a DHCP server on your network that is providing your host its IP address and the DSN servers.
You can change the DHCP configuration or force the first lines of resolv.confas #sahilKataria suggested. Using your command:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolvconf/resolv.conf.d/head
Edit your netplan file. Example:
sudo vim /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
ethernets:
enp0s31f6:
dhcp4: true # Using DHCP
dhcp4-overrides: # Override DHCP
use-dns: false # Disable DHCP DNS
routes:
- to: x.x.x.x/24
via: x.x.x.x
metric: 100
- to: x.x.x.x/24
via: x.x.x.x
metric: 100
nameservers: # Name Server section
search: [somename.ddns.net] # Set your nameserver search
addresses: [x.x.x.x] # Set your DNS Server
version: 2
When you are done, run:
netplan apply
And make sure that you have this:
$ ls -ltra /etc/resolv.conf
/etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
If bind is installed on the same machine:
$ cat /etc/hosts
127.0.1.1 somename.ddns.net somename # example
bind-ipaddress somename.ddns.net somename # example

How to determine the subnet mask and network interface card from remote SSH login?

In a separate question (link below), it was suggested that I obtain the network interface card number and subnet mask from a remote SSH login, rather than prompting the user for it. All I have is the IP address of my remote host. I need to obtain the subnet mask to determine if the remote and local host are on the same subnet, and the interface card number to set up and configure a virtual IP for aliasing purposes.
Could someone suggest how I might be able to parse out the necessary information and return it to my shell script that initiates the remote ssh connection? My target hosts have Linux or AIX as the operating system. I am familiar with the netstat function, but I'm not sure if parsing information from this is valid, or if there is a better way to get what I need that will work for both Linux and AIX operating systems.
Thanks for any help you can provide!
How to return from shell 'read' command passed in expect script?
--UPDATE--
AIX ifconfig -a:
$ ifconfig -a
en0: flags=1e080863,480<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPR
T,64BIT,CHECKSUM_OFFLOAD(ACTIVE),CHAIN>
inet 10.105.65.131 netmask 0xffff0000 broadcast 10.105.255.255
tcp_sendspace 262144 tcp_recvspace 262144 rfc1323 1
lo0: flags=e08084b,c0<UP,BROADCAST,LOOPBACK,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64
BIT,LARGESEND,CHAIN>
inet 127.0.0.1 netmask 0xff000000 broadcast 127.255.255.255
inet6 ::1%1/0
tcp_sendspace 131072 tcp_recvspace 131072 rfc1323 1
AIX netstat -rn:
$ netstat -rn
Routing tables
Destination Gateway Flags Refs Use If Exp Groups
Route tree for Protocol Family 2 (Internet):
default 10.105.65.1 UG 31 39412125 en0 - -
10.105.0.0 10.105.65.131 UHSb 0 0 en0 - - =
>
10.105/16 10.105.65.131 U 219 985607244 en0 - -
10.105.65.131 127.0.0.1 UGHS 5 1326738 lo0 - -
10.105.255.255 10.105.65.131 UHSb 3 6926640 en0 - -
127/8 127.0.0.1 U 36 11962928 lo0 - -
Route tree for Protocol Family 24 (Internet v6):
::1%1 ::1%1 UH 1 393270 lo0 - -
I tried route get and that doesn't work on my AIX box to tell me the route. The only thing I can get to work is netstat -rn. I'm not sure if there is another command similar to ip route that would work.
The Linux boxes support both ip and ifconfig.
I am not sure what to do when there are multiple network interface cards, as I do not know which one really should be used when setting up a virtual IP.
The Linux setup is more what I am concerned with, as I will be eventually adding in the AIX support for my software installation script later and can do more research on it then.
For Linux, I might do this something like so (using bash extensions, so invoked using a #!/bin/bash shebang, or piping the script over stdin to an interpreter invoked as ssh "$hostname" bash <<'EOF'):
internet_address=8.8.8.8 # read data for the NIC used to route here
dev_re='dev ([^[:space:]]+)($|[[:space:]])'
read default_route < <(ip -o route get "$internet_address")
[[ $default_route =~ $dev_re ]] && devname=${BASH_REMATCH[1]}
IFS=$'\n' read -r -d '' -a addresses < \
<(netstat -rn |
awk -v dev="$devname" '$8 == dev && ($2 == "0.0.0.0" || $2 == "default") { print $1 }')
# emit this output however you like
printf '%s\n' "$dev_re" "${addresses[#]}"

Isolated test network on a Linux server running a web server (lightttpd) and (curl) clients

I'm writing a testing tool that requires known traffic to be captured from a NIC (using libpcap), then fed into the application we are trying to test.
What I'm attempting to set-up is a web server (in this case, lighttpd) and a client (curl) running on the same machine, on an isolated test network. A script will drive the entire setup, and the goal is to be able to specify a number of clients as well as a set of files for each client to download from the web server.
My initial approach was to simply use the loopback (lo) interface... run the web server on 127.0.0.1, have the clients fetch their files from http://127.0.0.1, and run my libpcap-based tool on the lo interface. This works ok, apart from the fact that the loopback interface doesn't emulate a real Ethernet interface. The main problem with that is that packets are all inconsistent sizes... 32kbytes and bigger, and somewhat random... it's also not possible to lower the MTU on lo (well, you can, but it has no effect!).
I also tried running it on my real interface (eth0), but since it's an internal web client talking to an internal web server, traffic never leaves the interface, so libpcap never sees it.
So then I turned to tun/tap. I used socat to bind two tun interfaces together with a tcp connection, so in effect, i had:
10.0.1.1/24 <-> tun0 <-socat-> tcp connection <-socat-> tun1 <-> 10.0.2.1/24
This seems like a really neat solution... tun/tap devices emulate real Ethernet devices, so i can run my web server on tun0 (10.0.1.1) and my capture tool on tun0, and bind my clients to tun1 (10.0.2.1)... I can even use tc to apply shaping rules to this traffic and create a virtual WAN inside my linux box... but it just doesn't work...
Here are the socat commands I used:
$ socat -d TCP-LISTEN:11443,reuseaddr TUN:10.0.1.1/24,up &
$ socat TCP:127.0.0.1:11443 TUN:10.0.2.1/24,up &
Which produces 2 tun interfaces (tun0 and tun1), with their respective IP addresses.
If I run ping -I tun1 10.0.1.1, there is no response, but when i tcpdump -n -i tun0, i see the ICMP echo requests making it to the other side, just no sign of the response coming back.
# tcpdump -i tun0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 65535 bytes
16:49:16.772718 IP 10.0.2.1 > 10.0.1.1: ICMP echo request, id 4062, seq 5, length 64
<--- insert sound of crickets here (chirp, chirp)
So am I missing something obvious or is this the wrong approach? Is there something else i can try (e.g. 2 physical interfaces, eth0 and eth1???).
The easiest way is just to use 2 machines, but I want all of this self-contained, so it can all be scripted and automated on a single machine, without and other dependencies...
UPDATE:
There is no need for the 2 socats to be connected with a tcp connection, it's possible (and preferable for me) to do this:
socat TUN:10.0.1.1/24,up TUN:10.0.2.1/24,up &
The same problem still exists though...
OK, so I found a solution using Linux network namespaces (netns). There is a helpful article about how to use it here: http://code.google.com/p/coreemu/wiki/Namespaces
This is what I did for my setup....
First, download and install CORE: http://cs.itd.nrl.navy.mil/work/core/index.php
Next, run this script:
#!/bin/sh
core-cleanup.sh > /dev/null 2>&1
ip link set vbridge down > /dev/null 2>&1
brctl delbr vbridge > /dev/null 2>&1
# create a server node namespace container - node 0
vnoded -c /tmp/n0.ctl -l /tmp/n0.log -p /tmp/n0.pid > /dev/null
# create a virtual Ethernet (veth) pair, installing one end into node 0
ip link add name veth0 type veth peer name n0.0
ip link set n0.0 netns `cat /tmp/n0.pid`
vcmd -c /tmp/n0.ctl -- ip link set n0.0 name eth0
vcmd -c /tmp/n0.ctl -- ifconfig eth0 10.0.0.1/24 up
# start web server on node 0
vcmd -I -c /tmp/n0.ctl -- lighttpd -f /etc/lighttpd/lighttpd.conf
# create client node namespace container - node 1
vnoded -c /tmp/n1.ctl -l /tmp/n1.log -p /tmp/n1.pid > /dev/null
# create a virtual Ethernet (veth) pair, installing one end into node 1
ip link add name veth1 type veth peer name n1.0
ip link set n1.0 netns `cat /tmp/n1.pid`
vcmd -c /tmp/n1.ctl -- ip link set n1.0 name eth0
vcmd -c /tmp/n1.ctl -- ifconfig eth0 10.0.0.2/24 up
# bridge together nodes using the other end of each veth pair
brctl addbr vbridge
brctl setfd vbridge 0
brctl addif vbridge veth0
brctl addif vbridge veth1
ip link set veth0 up
ip link set veth1 up
ip link set vbridge up
This basically sets up 2 virtual/isolated/name-spaced networks on your Linux host, in this case, node 0 and node 1. A web server is started on node 0.
All you need to do now is run curl on node 1:
vcmd -c /tmp/n1.ctl -- curl --output /dev/null http://10.0.0.1
And monitor the traffic with tcpdump:
tcpdump -s 1514 -i veth0 -n
This seems to work quite well... still experimenting, but looks like it will solve my problem.

Resources