12

I'm looking for a specific place to add some kind of hook to the linux kernel that will allow me to do the following:

  • Detect just the case of a TCP connection going to loopback (127.0.0.1)
  • Detect if the source process of the packet is the same as the destination process
  • If this is the case, allow the connection, deny any other loopback connection (one process to another process)

I've been looking at netfilter hooks but they don't seem to fit the need. bpf filters only look at the packet itself.

I was also looking at the LSM hook of socket-connect. I can try to achieve this from the socket-connect hook by looking at what process has the requested port current bound to predict where the connection is going to connect that this sounds quite hackish.

shoosh
  • 76,898
  • 55
  • 205
  • 325
  • TCP connections are not necessarily associated with a single process. File descriptors are inherited by child processes when forking, and can also be passed between processes using `sendmsg()`. – Barmar Dec 05 '18 at 22:56
  • @Barmar that's a good point. If any of the sides of the socket has more than one process associated with it then that's also a connection I want to deny. Got any lead on where to put such a hook? – shoosh Dec 06 '18 at 07:34
  • Take a look here: https://www.usna.edu/Users/cs/aviv/classes/ic221/s16/lec/21/lec.html As far as I can see, there's no pointers from the file table back to the process table. So you need to scan through all processes' file descriptors, looking for one that points to the socket in question. – Barmar Dec 06 '18 at 17:21
  • @shoosh By using SELinux socket hook function implementation you can manage the security fields of socket structure and perform access control for socket operations. – Kousic Dec 18 '18 at 06:33
  • @Kousic SELinux does not have a hook called for confirming loopback connections. It only has the LSM hook I mentioned that allows you to confirm a call to connect() – shoosh Dec 18 '18 at 10:05
  • @shoosh Agreed! Now, what is your linux version ? and which OS you are using? – Kousic Dec 18 '18 at 10:09
  • Can you please give me a specific requirement with more detail that you are seeking currently? – Kousic Dec 18 '18 at 10:32
  • I don't have an exact answer, however I think primary problem is to check what process made a reuqest. Here a good starting point https://unix.stackexchange.com/questions/56988/how-can-i-find-which-process-sends-data-to-a-specific-port – rakwaht Dec 18 '18 at 14:41
  • @Kousic why does it matter? I'm on 4.19 kernel. OS is Linux probably but it might be temple-os. The specific require is written in the question. – shoosh Dec 18 '18 at 15:59
  • Amm... why not use [`pipe`](http://man7.org/linux/man-pages/man2/pipe.2.html) instead of TCP/IP? By using pipes you have total control over the file descriptor and no external process can connect to the pipe unless it's a child process (which you would control)...? – Myst Dec 19 '18 at 19:08
  • @Myst I don't have control over what's being used. I'm trying to harden the system against malicious processes – shoosh Dec 20 '18 at 07:32
  • @shoosh Security-enhanced Linux (SELinux) is a project that has integrated role based access control and type enforcement into the standard Linux kernel. Some of the distinctive characteristics of the Security-enhanced Linux system include like controls over Sockets, Messages, and Network Interfaces etc,. – Kousic Dec 20 '18 at 10:48
  • It would provide a set of security hooks to control operations on kernel objects and a set of opaque security fields in kernel data structures for maintaining security attributes. – Kousic Dec 20 '18 at 10:50
  • @Kousic did you actually read the question? – shoosh Dec 20 '18 at 15:25
  • @shoosh Yes I read, but i don't understand your actual requirement? Because Linux is very deep concept. So, you should describe it very clearly.. – Kousic Dec 20 '18 at 18:26

1 Answers1

5

A simple approach could be the use of Linux network namespaces.

Linux Network Namespaces

As the name would imply, network namespaces partition the use of the network—devices, addresses, ports, routes, firewall rules, etc.—into separate boxes, essentially virtualizing the network within a single running kernel instance. Network namespaces entered the kernel in 2.6.24,...

see https://lwn.net/Articles/580893/

Unshare

unshare() allows a process (or thread) to disassociate parts of its execution context that are currently being shared with other processes (or threads).

see http://man7.org/linux/man-pages/man2/unshare.2.html

Testcase

Since a program should be able to comunicate with itself we need a program that communicates with itself via sockes. There is a cool SO answer that shows a simple Java program that transfers the text 'Hello World!' via socket to itself, see here https://stackoverflow.com/a/8119708.

/usr/bin/java SendReceive

works as expected and gives the output 'Hello World!'

With the -n option one can unshare network namespace.

unshare -n -- sh -c '/usr/bin/java SendReceive'

gives a SocketException: Network is unreachable because there is no access to the loopback device.

unshare -n -- sh -c 'ip link set dev lo up; /usr/bin/java SendReceive'

finally transfers 'Hello World!' again via a loopback interface. BTW: this is a private loopback device. You cannot access open ports on the standard loopback device.

See also this cool Unix Stackexchange answer: https://unix.stackexchange.com/a/83348: Block network access of a process?

Screenshot

Here a screenshot of the test case mentioned above executed on Ubuntu 18.10:

screenshot

Stephan Schlecht
  • 26,556
  • 1
  • 33
  • 47