How to resolve "setsockopt(3, SOL_SOCKET, SO_MARK, [10], 4) = -1 EPERM" Operation denied for none root users - linux

I got two network interfaces (ethernet and wlan). Now I found a little script on github (https://github.com/Intika-Linux-Firewall/App-Route-Jail) which seems to allow me to route specific applications through the none default gateway to loadbalance the traffic a little bit.
The script is using the following call:
setsockopt(sd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
As I found out via an strace I got: '-1 EPERM Permission denied' (as show on http://man7.org/linux/man-pages/man7/capabilities.7.html this command needs cap_net_admin rights)
The tool works when I use "sudo" infront of the command the socket is created with the none default gateway and works like intended (e.g. wget a file)
Example:
MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me uses the default gateway (so not what I wanted)
sudo MARK=10 LD_PRELOAD=./mark.so wget -qO- ifconfig.me returns the IP of the none default gateway (what I want but without using sudo)
Some things I found on the internet and tried:
Setting File Capabilities (setcap cap_net_admin+eip) (still requires root somehow)
Using SUID Bit (chmod u+s) (no change at all)
I expect the command to run without root privileges, so every application can use the none default gateway, but currently I need to use sudo to gain enough permissions to run the command on the correct interface.
What am I missing to archive my goals?

You are looking to your problem from the wrong angle. Instead of marking the packets, you should try to force the application to bind to the correct interface in the first place.
You could try the retro-solution explained here, which overrides bind() and connect() instead of socket().
But more modern solution would be to create a separate network namespace and then run applications in their own namespace. Google ip netns for the examples. Creating and setting up the network namespace still requires root, but these privileges can be dropped before running the application. There are likely to be tools available to do that also.

Related

FortiClient headless linux cli - how to install and configure to handle certain IP ranges only or permit SSH

I am trying to configure the headless VPN only FortiClient on an AWS ubuntu 20.04 ec2 instance, and though I am able to connect to the target, I am then disconnected from the instance and cannot progress.
Setup:
wget http://cdn.software-mirrors.com/forticlientsslvpn_linux_4.4.2328.tar.gz
tar -xzvf forticlientsslvpn_linux_4.4.2328.tar.gz
cd ./forticlientsslvpn/64bit/helper
sudo ./setup.linux.sh
# Accept license
cd ..
./forticlientsslvpn_cli --server serveraddress:port --vpnuser username
# Enter password
##Connected!
At this stage, I am booted out of the instance and cannot reconnect (requiring a soft restart of the instance to gain access again)
I can see that there is a configuration file at forticlientsslvpn/64bit/helper/config but I cannot find any documentation describing what can be configured there or whether it is something I should be concerned with.
The CLI itself doesn't take any other options other than:
forticlientsslvpn_cli [--proxy proxyaddress:proxyport] --server vpnserveraddress:vpnport [--proxyuser proxyuser] [--vpnuser vpnuser] [--pkcs12 pkcs12path] [--keepalive]
I would like to either:
Preserve my original SSH connection (and any future connections) so I can develop within the VPN or;
Limit the VPN to only package traffic that is going to a specific IP range (CIDR block)
I have found three different methods for installing the client (sudo apt install forticlient, sudo apt install -y openfortivpn, see above) and cannot navigate through them. I have looked into FortiClientLinuxGuide and installed that tool but couldn't find out how to configure it as a VPN instead (or where to add the configuration). Similar experience with the second one.
This seems to be the only documentation about how to configure the CLI and its just the bear minimum How to setup and install SSLVPN.
This post seems to be having the same problem ssh-telnet-disconnects and the solution looks like it would work if only I knew how to set that configuration.
alternatively, I have looked up split tunnel configuration which looks like it would be ideal but cannot work out how I would set that up. The documentation is only via the GUI Enable-split-tunnel-feature

Linux Lua: Permission denied on https request

I've been trying to send a https request using ssl.https library in Lua, however no matter what url I give, I alway get permission denied and no other values like headers, etc. The linux I am using is CentOS Linux version 7.
Here is the example code:
local httpsocket = require("socket.http")
local httpssocket = require ("ssl.https")
local ltn12 = require("ltn12")
local res, code, response_headers, status = httpssocket.request("https://www.google.com")
module:log("info","%s %s",code.."",response_headers);
The code itself is part of a prosody plugin and the last line in this example prints this out:
permission denied <nil>
My question is how do I fix this issue so that I can access the page?
EDIT: It seem that the problem might be the user that the service is run under and needs root privilages otherwise it throws ACCES error for ports lower than 1024. Does anyone know what to do in this case?
So... after attempting fix this issue again, I finally found the solution. If you are having trouble with services not being able to send http/https request on centOS, there is a single command that has to be run to fix this issue:
setsebool -P nis_enabled 1
For those who might have similar issues but not quite the same as me, look into the /var/log/audit/audit.log for anything related to your program, process, service, etc. then use this command:
grep <pattern_to_match_specific_log> /var/log/audit/audit.log | audit2why
This will give you a reason why it failed and how to fix it

setcap cap_net_admin in linux containers prevents user access to every file

I have a tcpdump application in a CentOS container. I was trying to run tcpdump as nonroot. Following this forum post: https://askubuntu.com/questions/530920/tcpdump-permissions-problem (and some other documentation that reinforced this), I tried to use setcap cap_net_admin+eip /path/to/tcpdump in the container.
After running this, I tried to run tcpdump as a different user (with permissions to tcpdump) and I got "Operation Not Permitted". I then tried to run it as root which had previously been working and also got, "Operation Not Permitted". After running getcap, I verified that the permissions were what they should be. I thought it may be my specific use case so I tried running the setcap command against several other executables. Every single executable returned "Operation Not Permitted" until I ran setcap -r /filepath.
Any ideas on how I can address this issue, or even work around it without using root to run tcpdump?
The NET_ADMIN capability is not included in containers by default because it could allow a container process to modify and escape any network isolation settings applied on the container. Therefore explicitly setting this permission on a binary with setcap is going to fail since root and every other user in the container is blocked from that capability. To run a container with this, you would need to add this capability onto the container with the command used to start your container. e.g.
docker run --cap-add NET_ADMIN ...
However, I believe all you need is NET_RAW (setcap cap_net_raw) which is included in the default capabilities. From man capabilities:
CAP_NET_RAW
* Use RAW and PACKET sockets;
* bind to any address for transparent proxying.

How can dhclient be made namespace aware?

I am using namespaces to separate a few physical interfaces on a server. The routing works perfectly.
Also I have a folder for each namespace in /etc/netns/ e.g. /etc/netns/namespaceA/resolv.conf so that DNS works fine as well.
The problem arises when using DHCP with dhclient.
I am running dhclient from inside a namespace and am getting this error.
(namespaceA)root#tc-vm:~#dhclient
RTNETLINK answers: File exists
mv: cannot move '/etc/resolv.conf.dhclient-new.2740' to '/etc/resolv.conf': Device or resource busy
I found out that the mv in /etc/resolvconf/update.d/libc contains a mv which might cause the problem.
How can dhclient be made namespace aware?
I looked into the issue myself.
What happens is that when you create a network namespace, you see /etc/resolv.conf of the host machine unless you create explicitly /etc/netns/<namespace_name>/resolv.conf, which will bind mount automatically to /etc/resolv.conf when looked up inside the network namespace. Therefore, by simply creating that path, the resolv.conf of the host won't be visibile any more on the network namespace, which will have its own resolv.conf.
The manual page of ip netns explains this:
For applications that are aware of network namespaces, the convention
is to look for global network configuration files first in
/etc/netns/NAME/ then in /etc/. For example, if you want a different
version of /etc/resolv.conf for a network namespace used to isolate
your vpn you would name it /etc/netns/myvpn/resolv.conf.
Ip netns exec automates handling of this configuration, file
convention for network namespace unaware applications, by creating a
mount namespace and bind mounting all of the per network namespace
configure files into their traditional location in /etc.
As far as updating resolv.conf, dhclient doesn't work in network namespaces out of the box when /etc/netns/<namespace_name>/resolv.conf exists (on the other hand, when it doesn't exist, it will overwrite the resolv.conf of the host machine, since it's the only one available, but that's not really desirable). As the error in the question above shows, what happens is that dhclient prepares a temporary file with the new nameserver details in /etc/resolv.conf.dhclient-new.2740 and then tries to rename it as /etc/resolv.conf. It generates an error because /etc/resolv.conf is already bind-mounted and apparently mv isn't allowed to do this trick.
In order to make dhclient work in network namespaces, /sbin/dhclient-script should be modified.
I removed this:
mv -f $new_resolv_conf /etc/resolv.conf
And replaced it with:
cat $new_resolv_conf > /etc/resolv.conf
rm -f $new_resolv_conf
Otherwise, dhcpcd seems to do this job correctly.

NT_STATUS_ACCESS_DENIED Error in Samba share

So, I tried to set up a public SMB share with Samba on CentOS 7. Now, I have it set up, and I have a headache. But, sweet victory. I'm posting this here for all y'all so that you don't need to waste your time. It's actually easy, you just need to know the hoops you need to jump through. I'll also edit the Samba wiki.
The first problem was that it wouldn't connect at all, except locally:
Remote Connection (my Linux desktop):
-------
[root#my-desktop ~]# smbclient //sambaserver/PublicDocs -N
Error connecting to 192.168.100.97 (No route to host)
Connection to cgybkp01 failed (Error NT_STATUS_HOST_UNREACHABLE)
On Windows 8, using Windows Explorer, after typing "\\sambaserver" into the address bar, the progress bar would wait, wait, wait, then time out. The error message was:
Remote Connection (my Windows 8 desktop):
Windows cannot access \\sambaserver
Check the spelling of the name. Otherwise, there might be a problem with your network. To
try to identify and resolve network problems, click Diagnose.
This ended up being a problem with firewalld. To unblock Samba, I needed to add this line to /etc/firewalld/zones/public.xml :
<service name="samba"/>
Perfect, now I can connect!
But, I was actually mounting an NFS share, so I had one more issue, with SELinux. Now, when I attempt to connect with smbclient...
smbclient //sambaserver/PublicDocs -N
I can connect, but when I try to ls, I get the error: "NT_STATUS_ACCESS_DENIED" in CentOS 7. So, how do I connect?
The first thing everyone recommended that I try was file permissions. If you're not familiar with file permissions in Linux, I'd recommend trying those first. But for me, that didn't work, because SELinux was blocking me.
To see all of the SELinux options for Samba, type:
getsebool -a | grep samba
getsebool -a | grep smb
The one I needed to change was samba_share_nfs, because I was sharing an NFS mounted directory:
setsebool -P samba_share_nfs on
CentOS maintains a list of these booleans here.

Resources