Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SELinux policy for vpn client #82

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions cli/python/src/client/resources/selinux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SELinux policy

*Tested on Fedora*

1. Prerequisites packages:
- setroubleshoot
- policycoreutils
- policycoreutils-devel

2. Other prerequisites:
- The `playio-vpnc` executatble folder path is existed, it's defaulted to `/app`
- Enable SELinux [boolean](https://wiki.gentoo.org/wiki/SELinux/Tutorials/Using_SELinux_booleans):
```bash
setsebool -P domain_can_mmap_files 1
setsebool -P domain_kernel_load_modules 1
setsebool -P daemons_enable_cluster_mode 1
```

3. Build and install the policy module:

Change to this folder `selinux` and run below command:

```bash
make -f /usr/share/selinux/devel/Makefile playio_vpnc.pp
semodule -i playio_vpnc.pp
restorecon -FRv /app
```

[**More information**](./playio_selinux.md)
54 changes: 54 additions & 0 deletions cli/python/src/client/resources/selinux/playio_selinux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# PlayIO SELinux

This page describes briefly about the policy module we created for working on system with SELinux enabled.

## Overview

Custom SELinux policy module should be installed prior to VPN client installation.

We tend to create a custom SELinux type enforcement policy module, all the resources to build it contains:
- The file contexts expressions `playio_vpnc.fc` file, data in this file is the reference in labelling step (the `restorecon` command, for example)
- The module interface definition `playio_vpnc.if` file, it defines set of *public functions* that other modules can use to properly interact with the `vpnc_playio` module we're about to create
- The rules definition `playio_vpnc.te` file, this file is considered the most important in the module: it defines type enforcement rules.
- The policy binary file `playio_vpnc.pp` which is compiled from 3 above source files. This file is installed into system's SELinux policy

### File contexts expressions

This file is identified by its extension `.fc`

We define label for files are belong to `playio_vpnc`: label for executable and label for the whole resources

### Module interface definition

Basically, we define `playio_vpnc_domtrans` interface allows other processes (called domain in context of SELinux) to do a domain transition to `playio_vpnc_t` by executing our program which is labeled `playio_vpnc_exec_t`

The other interface `playio_vpnc_exec` we defined allows other domains to execute our program labeled `playio_vpnc_exec_t`

### Rules definition

Set of rules to allow VPNC client to be run and interacted with multiple elements of the system: file system, network socket, unix socket, other processes/applications...

For example, this rule:
```
allow playio_vpnc_t dhcp_etc_t:dir { getattr search };
```
Can be described as: allow domain labeled `playio_vpnc_t` to search and get attributes on directories of the directory type labeled `dhcp_etc_t`. In this case, our VPN client generates a hook script and put into `/etc/dhcp/dhclient-exit-hooks.d` directory. The SElinux context of this directory is `unconfined_u:object_r:dhcp_etc_t:s0` as below:
```
$ sudo ls -lZ /etc/dhcp/
total 0
drwxr-xr-x. 2 root root system_u:object_r:bin_t:s0 23 May 12 05:59 dhclient.d
drwxr-xr-x. 2 root root unconfined_u:object_r:dhcp_etc_t:s0 24 Jun 5 17:31 dhclient-exit-hooks.d
```
Where the 3rd field (":" separated) is the domain type: `dhcp_etc_t`

Some references:
- https://wiki.gentoo.org/wiki/SELinux
- https://debian-handbook.info/browse/stable/sect.selinux.html

## How this policy got composed

- Set system's SELinux operation to `permissive` mode, in this mode nothing's got prohibitted by SELinux but all policy violations are logged to system log or audit log.
- Install and configure VPN client as usual.
- Analyze the log and generate rules, some useful tools to help achieve this task: `ausearch`, `journalctl`, `sealert`

**Contribution:** There're always rooms for improvement, we really appreciate your contribution and suggestion in documenting and improving this custom policy module.
2 changes: 2 additions & 0 deletions cli/python/src/client/resources/selinux/playio_vpnc.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/app/playio-vpnc -- gen_context(system_u:object_r:playio_vpnc_exec_t,s0)
/app(/.*)? gen_context(system_u:object_r:playio_vpnc_t,s0)
40 changes: 40 additions & 0 deletions cli/python/src/client/resources/selinux/playio_vpnc.if
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

## <summary>policy for playio_vpnc</summary>

########################################
## <summary>
## Execute playio_vpnc_exec_t in the playio_vpnc domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`playio_vpnc_domtrans',`
gen_require(`
type playio_vpnc_t, playio_vpnc_exec_t;
')

corecmd_search_bin($1)
domtrans_pattern($1, playio_vpnc_exec_t, playio_vpnc_t)
')

######################################
## <summary>
## Execute playio_vpnc in the caller domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`playio_vpnc_exec',`
gen_require(`
type playio_vpnc_exec_t;
')

corecmd_search_bin($1)
can_exec($1, playio_vpnc_exec_t)
')
165 changes: 165 additions & 0 deletions cli/python/src/client/resources/selinux/playio_vpnc.te
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
policy_module(playio_vpnc, 1.0.0)

########################################
#
# Declarations
#

type playio_vpnc_t;
files_type(playio_vpnc_t)

type playio_vpnc_exec_t;
init_daemon_domain(playio_vpnc_t, playio_vpnc_exec_t)

permissive playio_vpnc_t;

########################################
#
# playio_vpnc local policy
#
require {
type bin_t;
type chronyd_exec_t;
type devlog_t;
type dhcp_etc_t;
type dhcpc_exec_t;
type dhcpc_port_t;
type dhcpc_state_t;
type dnsmasq_exec_t;
type fs_t;
type http_port_t;
type ifconfig_exec_t;
type init_t;
type kernel_t;
type net_conf_t;
type NetworkManager_t;
type node_t;
type proc_t;
type random_device_t;
type shell_exec_t;
type sssd_public_t;
type sssd_t;
type sssd_var_lib_t;
type sysfs_t;
type syslogd_var_run_t;
type systemd_systemctl_exec_t;
type tmp_t;
type tmpfs_t;
type tun_tap_device_t;
type unreserved_port_t;
type var_log_t;

class capability { net_bind_service net_raw };
class chr_file { ioctl open read write };
class dir { add_name create getattr open read remove_name rmdir search write };
class file { create execute execute_no_trans getattr ioctl map open read setattr unlink write };
class filesystem getattr;
class netlink_route_socket { bind create getattr getopt nlmsg_read setopt };
class packet_socket { bind create ioctl setopt };
class process { execmem getpgid setrlimit };
class rawip_socket { bind create getattr getopt node_bind setopt };
class sock_file write;
class system module_request;
class tcp_socket { accept bind connect create getattr getopt listen name_bind name_connect node_bind setopt shutdown };
class tun_socket create;
class udp_socket { bind connect create getattr getopt ioctl name_bind node_bind setopt };
class unix_dgram_socket { connect create sendto };
class unix_stream_socket connectto;
}

allow playio_vpnc_t self:capability { net_raw net_bind_service };
allow playio_vpnc_t self:dir { add_name remove_name write search};
allow playio_vpnc_t self:fifo_file rw_fifo_file_perms;
allow playio_vpnc_t self:file { create execute execute_no_trans map open rename unlink setattr write read };
allow playio_vpnc_t self:netlink_route_socket { bind create getattr getopt nlmsg_read setopt };
allow playio_vpnc_t self:packet_socket { bind create ioctl setopt };
allow playio_vpnc_t self:process { execmem fork getpgid setrlimit signal_perms };
allow playio_vpnc_t self:rawip_socket { bind create getattr getopt setopt };
allow playio_vpnc_t self:tcp_socket { accept bind connect create getattr getopt listen setopt shutdown };
allow playio_vpnc_t self:tun_socket create;
allow playio_vpnc_t self:udp_socket { bind connect create getattr getopt ioctl setopt };
allow playio_vpnc_t self:unix_dgram_socket { connect create };
allow playio_vpnc_t self:unix_stream_socket create_stream_socket_perms;

allow playio_vpnc_t bin_t:file { execute execute_no_trans };

allow playio_vpnc_t chronyd_exec_t:file { execute execute_no_trans open read };

allow playio_vpnc_t devlog_t:lnk_file read;
allow playio_vpnc_t devlog_t:sock_file write;
allow playio_vpnc_t dhcp_etc_t:dir { getattr search };
allow playio_vpnc_t dhcp_etc_t:file { open read };
allow playio_vpnc_t dhcpc_exec_t:file { execute execute_no_trans getattr ioctl map open read };
allow playio_vpnc_t dhcpc_port_t:udp_socket name_bind;
allow playio_vpnc_t dhcpc_state_t:dir search;
allow playio_vpnc_t dnsmasq_exec_t:file { execute getattr };

allow playio_vpnc_t fs_t:filesystem getattr;

allow playio_vpnc_t http_port_t:tcp_socket name_connect;

allow playio_vpnc_t ifconfig_exec_t:file { execute execute_no_trans getattr open read };
allow playio_vpnc_t init_t:file { getattr ioctl open read };
allow playio_vpnc_t init_t:lnk_file read;
allow playio_vpnc_t init_t:unix_stream_socket connectto;

allow playio_vpnc_t kernel_t:system module_request;
allow playio_vpnc_t kernel_t:unix_dgram_socket sendto;

allow playio_vpnc_t net_conf_t:dir { getattr open read search };
allow playio_vpnc_t net_conf_t:file { getattr open read };
allow playio_vpnc_t net_conf_t:lnk_file { getattr read };
allow playio_vpnc_t NetworkManager_t:dir search;
allow playio_vpnc_t NetworkManager_t:file { getattr ioctl open read };
allow playio_vpnc_t node_t:rawip_socket node_bind;
allow playio_vpnc_t node_t:tcp_socket node_bind;
allow playio_vpnc_t node_t:udp_socket node_bind;

allow playio_vpnc_t playio_vpnc_exec_t:file execute_no_trans;
allow playio_vpnc_t proc_t:file { getattr ioctl open read };

allow playio_vpnc_t random_device_t:chr_file { open read };

allow playio_vpnc_t shell_exec_t:file { execute execute_no_trans map };
allow playio_vpnc_t sssd_t:unix_stream_socket connectto;
allow playio_vpnc_t sssd_public_t:dir search;
allow playio_vpnc_t sssd_public_t:file { getattr map open read };
allow playio_vpnc_t sssd_var_lib_t:dir search;
allow playio_vpnc_t sssd_var_lib_t:sock_file write;
allow playio_vpnc_t sysfs_t:file { getattr open read };
allow playio_vpnc_t sysfs_t:lnk_file read;
allow playio_vpnc_t syslogd_var_run_t:dir { getattr open read search };
allow playio_vpnc_t systemd_systemctl_exec_t:file map;

allow playio_vpnc_t tmp_t:dir { add_name create read remove_name rmdir write };
allow playio_vpnc_t tmp_t:file { create execute map setattr unlink write };
allow playio_vpnc_t tmpfs_t:filesystem getattr;
allow playio_vpnc_t tun_tap_device_t:chr_file { ioctl open read write };

allow playio_vpnc_t unreserved_port_t:tcp_socket { name_bind name_connect };

allow playio_vpnc_t var_log_t:dir read;
allow playio_vpnc_t var_log_t:file { map open read };

domain_use_interactive_fds(playio_vpnc_t)

files_read_etc_files(playio_vpnc_t)

miscfiles_read_localization(playio_vpnc_t)

##########################################
#
# dnsmasq local policy for playio_vpnc
#
require {
type dnsmasq_t;
type dnsmasq_etc_t;
type NetworkManager_etc_t;
class lnk_file { getattr read };
}

#============= dnsmasq_t ==============
allow dnsmasq_t dnsmasq_etc_t:lnk_file read;
allow dnsmasq_t NetworkManager_etc_t:lnk_file read;
allow dnsmasq_t playio_vpnc_t:dir search;
allow dnsmasq_t playio_vpnc_t:file { open read getattr };