Network Namespaces In Linux Kernel

 

Introduction

Each kernel network namespace has its own network devices (even the loopback interface), IP addresses, firewall rules, the “/proc/net” and /sys/class/net directory trees, sockets, IP routing tables, port numbers,…etc

indexclone() is a system call used to create a child process. If the CLONE_NEWNET flag is set, then the child process will be created in a new network namespace. Execute system(“ip link”) and system(“ip netns”) in the child process and in the parent to see the difference.

unshare() system call which creates a new namespace and adds the current process to it.

setns() system call is used to join an existing namespace.

You can define a virtual network device (veth) in the namespace and you can create a tunnel between two virtual network devices from different namespaces. The implementation of this is like creating a pipe. To connect the namespace to the internet, a bridge need to be created in the root namespace and the virtual device (veth) in the child namespace will be linked/bounded to the bridge. The physical network device can be assigned only to the root namespace. Instead of creating a bridge, you can use IP forwarding with NAT rules in the root namespace.

The namespace is addresses by it name or by PID of a process inside the namespace.

If a service in a namespace has been infected, this will not affect other services in other namespaces. This is due to the isolation property.

Add New Network Namespace

We can use the “ip” networking configuration tool to play with namespaces.  The namespace can persist even if it has not processes running in it. To add new empty namespace:

# ip netns add BinanNameSpace

“BinanNameSpace” is the name of the new created namespace. A bind mount is created for “BinanNameSpace” under “/var/run/netns”.

Get The Current Namespaces

To get the current namespaces, execute: “ip netns” or “ls /var/run/netns

BinanNameSpace
qdhcp-ae4d3669-d1ab-4133-8ea6-059611dc524e
qrouter-f96c719a-56e9-4b52-b2cb-da326fc1a429

List The Interfaces In The Namespace

To list the interfaces inside the namespace, execute:

# ip netns exec BinanNameSpace ip link list

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Note we have only loopback interface and it is down so we cannot ping it:

# ip netns exec BinanNameSpace ping 127.0.0.1

connect: Network is unreachable

To make the loopback interface up: # ip netns exec BinanNameSpace ip link set dev lo up

# ip netns exec BinanNameSpace ping 127.0.0.1

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.035 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms
^C
— 127.0.0.1 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.034/0.037/0.044/0.008 ms

Create Virtual Network Device In The Namespace

To create a virtual network device (veth1) in the “BinanNamespace” and make it as a peer to veth0 in the root namespace:

# ip link add veth0 type veth peer name veth1

# ip link set veth1 netns BinanNameSpace

Set IP addresses To The Virtual Network Devices

For the veth0 in the root namespace: # ifconfig veth0 11.0.0.2/24 up

For the veth1 in the “BinanNameSpace”: # ip netns exec BinanNameSpace ifconfig veth1 11.0.0.1/24 up

Now to check the interface veth0:

# ifconfig veth0

veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 11.0.0.2  netmask 255.255.255.0  broadcast 11.0.0.255
…..

To check the interface eth1:

# ip netns exec BinanNameSpace ifconfig veth1
veth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 11.0.0.1  netmask 255.255.255.0  broadcast 11.0.0.255
……

Connection Test

To test the connection between the root namespace and “BinanNameSpace”, we ping in both direction:

From the root(veth0: 11.0.0.2) to BinanNameSpace(veth1:11.0.0.1):

# ping 11.0.0.1
PING 11.0.0.1 (11.0.0.1) 56(84) bytes of data.
64 bytes from 11.0.0.1: icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from 11.0.0.1: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 11.0.0.1: icmp_seq=3 ttl=64 time=0.044 ms
^C
— 11.0.0.1 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.036/0.040/0.044/0.008 ms

From BinanNameSpace (veth1:11.0.0.1) to the root namespace (veth0: 11.0.0.2):

# ip netns exec BinanNameSpace ping 11.0.0.2

PING 11.0.0.2 (11.0.0.2) 56(84) bytes of data.
64 bytes from 11.0.0.2: icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from 11.0.0.2: icmp_seq=2 ttl=64 time=0.034 ms
64 bytes from 11.0.0.2: icmp_seq=3 ttl=64 time=0.038 ms
^C
— 11.0.0.2 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.034/0.038/0.042/0.003 ms

Delete A Namespace

To delete the namespace, execute: # ip netns delete BinanNameSpace


 More Information


Restrictions of FIFO-based Communications in Linux

Problem Definition

To explain this we will take OpenSIPS’s fifo as an example. It is used to communicate with OpenSIPS’s management interface “Mi”. Assume “/tmp/opensips_fifo” is the fifo file. OpenSIPS is the owner of this pipe and OpenSIPS-CP wants to access/read/write to/from the pipe. As we know everything is a file in Linux so this pipe is just a file and we want to manage how OpenSIPS-CP or other programs can access this pipe to send requests or receive reponses to/from OpenSIPS. OpenSIPS is executed by user=opensips and group=opensips. OpenSIPS-CP is executed by user=apache and group=apache. To see this:  # ps -aux | grep httpd or opensips.

fifo

And we have this error message “Cannot connect to OpenSIPS Server via Management Interface (/tmp/opensips_fifo)“. Be sure you are using the right name of the fifo file. Be aware if there is a space at the front or at the end of file path. Be sure that you are talking with the intended OpenSIPS server in case you have many OpenSIPS instances working on the same machine. Be sure the opensips is simply running (OpenSIPS restart may solve the problem). If all that is ok and still you have the error message then start your journey through this article.

Here i have Fedora 20, PHP 5.5.17 , Apache 2.4, OpenSIPS-CP 6.0 , OpenSIPS 1.11. Do the corresponding of everything in your system.

What to Do

Temporarily disable SeLinux. We will come back to it.

  • Discretionary Access Control (DAC): In OpenSIPS configuration file we have this line “modparam(“mi_fifo”, “fifo_mode”, 0666)”  so OpenSIPs create the fifo file with the permission 666 (Owner=6,Group=6, Others=6) which is “prw-rw-rw-“. This means read and write permission for the owner, group, and the others. The letter p means this file is pipe.
  • User:Group Ownership: OpenSIPS-CP executed by apache so add apache user to opensips group if you don’t want to give permissions to others. For this, you can use # system-config-users. To list the members in the group:

# lid -g $groupName

  • Access Control List (ACL): use ACL to give permissions to a specific user For example let Apache user has rw access to the fifo file:

# setfacl -m u:apache:rw /tmp/opensips_fifo

To check the list

# getfacl /tmp/opensips_fifo

Eiciel is GNOME tool to visually configure the ACL entries. # yum install eiciel and to run it  # eiciel the GUI will open. Choose the directory and start editing the acl. Visual ACL

  • Programming Language Restrictions: The programming language may apply some kind of restrictions on accessing files. Web programming language like PHP has safe_mode and open_basedir features. Open /etc/php.ini to disable these. For example file_exists() php function check whether the file or directory is exists or not. This Function return False due to safe_mode restrictions. When safe_mode is enabled (safe_mode = On in php.ini), PHP checks to see if the owner of the current php script matches the owner of the file to be operated on. Safe_mode is removed in PHP-5  but we have to keep programming language restrictions in our minds.
  • Web Server Restrictions: For example Apache web server protects directories and files from hosts/web clients by defining policy rules in httpd.conf.

Example 1: “Linux root is inaccessible by everyone”

<Directory />
AllowOverride none
Require all denied
</Directory>

The default is denying access to the entirety of your server’s file system. You must explicitly permit access to the server’s directories

Example 2: The area /var/www/opensips-cp/web can be accessed by everyone:

<Directory  /var/www/opensips-cp/web>

Options Indexes FollowSymLinks MultiViews

AllowOverride None
Require all granted

</Directory>

  • PrivateTmp Feature: This is new feature since Fedora 16 and Red Hat Enterprise Linux 7. “PrivateTmp” is an option in systemd unit configuration files.

PrivateTmp: “Takes a boolean argument. If true sets up a new file system namespace for the executed processes and mounts a private /tmp directory inside it, that is not shared by processes outside of the namespace. This is useful to secure access to temporary files of the process, but makes sharing between processes via /tmp impossible. Defaults to false.”

If the fifo file which is shared between two processes (apache and opensips) created in /tmp so you have to disable this feature. To disable it do the following:

# vim /usr/lib/systemd/system/httpd.service

Change the line PrivateTmp=true to PrivateTmp=false

# systemctl –system daemon-reload

# systemctl restart httpd.service

  • Umask

It could be helpful if you check the umask of the running process which accessing the file and the umask of the file. umask of the specific file can be changed by setfacl command and graphically by Eiciel . To change the  umask of running process, take the id of the process for example httpd # ps -ef |grep httpd.  Enter the gdp # gdp –pid=httpd-Process-Id. To change the umask to 0, type  call umask(0) in gdp console. The umask will be 0 and the command will give you the previous umask value.

  • SeLinux: SeLinux might prevent the access to the file (access, link, unlink,…. ). Selinux Troubleshooter can help you to know how to fix this. How to allow for example httpd process to access FIFO file. Keep your eyes on the SeLinux alerts and do what the troubleshooter suggests. The file “/var/log/audit/audit.log”  contain the alerts and what you did is this:

# grep httpd /var/log/audit/audit.log | audit2allow -M minpol
# semodule -i minpol.pp

If you go through all the points above you will be able to solve the problem .Remember if you make any changes in the configuration file, restart the service.

Where to Look to Trace the Error

Reading the log files is the key (basically here /var/log/*). Make some changes in the configuration somewhere, restart the corresponding service and re-read the log files again. Repeat this till you get no errors. Now  in our use case of opensips’s fifo we can see a list of available fifo commands in opensips-cp web interface. This means Apache (opensips-cp) and the opensips can communicates through the fifo file.

snap11

OpenSIPS-CP can request the dialog information from OpenSIPS through the fifo file. See the figures below of the early dialog and the confirmed dialog.

dialog1

dialog2


Below is a php client which try to connect to opensips fifo file and send commands. Copy the text and save it in opensips-cp/web/Fifotest.php and then call it from the browser /ipaddress/cp/Fifotest.php. Use it to test the fifo connection.

Source: FIFO Client PHP Example