The OpenNET Project / Index page

[ новости/++ | форум | wiki | теги ]

Совместное использование SELinux и iptables
Используя утилиту Secmark можно организовать назначение в правилах iptables
SELinux-меток для сетевых пакетов, примерно также как осуществляется назначение
меток для локальных системных ресурсов. Подобное может использоваться для
предотвращения доступа сторонних процессов, не находящихся под контролем
SELinux, к определенному классу пакетов. Например, можно указать что запросы на
80 порт (метка http_packet_t) может отправлять только определенный web-браузер
(или процесс, имеющий SELinux-метку http_t) и никто иной.

По умолчанию все сетевые пакеты снабжаются меткой unlabeled_t, а для всех
подконтрольных процессов активируется правило, без ограничений разрешающее
отправку и прием пакетов:

   allow MYDOMAIN unlabed_t:packet { send recv };

При назначении меток для трафика при помощи Secmark разрешительная политика по
отношению к unlabed_t может привести к тому, что в случае отключения пакетного
фильтра или в момент его перезапуска, правила блокирования будут временно проигнорированы.

Попытаемся отключить автоматическую установку метки unlabeled_t, которая
назначается в Fedora Linux через SELinux-модуль unlabelednet. Если отключить
данный набор SELinux-политик, то все подконтрольные SELinux приложения потеряют
возможность отправлять и принимать пакеты с меткой unlabeled_t. Чтобы вернуть
таким программам возможность работы в сети для них необходимо подготовить
соответствующие SELinux-правила и пометить пакеты.


Для усиления защиты ноутбука было решено подготовить простые SELinux-политики,
запрещающие обращаться к внешним сетевым ресурсам всем системным сервисам,
ограниченным при помощи SELinux. Всем программ, запущенные в рамках сессии
пользователя, разрешено обращаться как ко внутренним, так и к внешним сетевым ресурсам.

Подготовлено три политики доступа к сети:

internal_packet_t: Iptables помечает меткой internal_packet_t все пакеты,
отправленные в локальную сеть или приходящие на текущую машину из локальной сети;

dns_external_packet_t: Iptables помечает меткой dns_external_packet_t все
внешние обращения к DNS-серверам (udp/tcp порт 53);

external_packet_t: Iptables помечает меткой external_packet_t все остальные
пакеты, не подпадающие под первые два правила;


Для упрощения генерации iptables-правил для назначения SELinux-меток был создан скрипт
secmarkgen:

  #!/bin/sh -e

  init() {
  # This just tells iptables to apply the same label to incoming packets as it did on outgoing
    echo $IPTABLES -F -t security
    echo $IPTABLES -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
 
  # Apply a label even if its on another port but is related
    echo $IPTABLES -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    echo 
    return

  }

  start() {
    # Create a chain for each class of packets we have.
    echo "$IPTABLES -t security -X $NAME 2> /dev/null"
    echo "$IPTABLES -t security -N $NAME"
  }

  fini() {
    # Label all other packets going internally to $TYPE:$MCS
    echo $IPTABLES -t security -A $NAME -j SECMARK --selctx system_u:object_r:$TYPE:$MCS
    echo $IPTABLES -t security -A $NAME -j CONNSECMARK --save
    echo $IPTABLES -t security -A $NAME -j ACCEPT
    echo 
  }

  setup_network() {

    if [ ! -z "$PORTS" ]; then
	if [ ! -z "$NETWORK" ]; then
            # Send packets going to an $NET httpd to the $NAME chain
	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL -d $NETWORK --dport $PORTS -j $NAME
	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL -d $NETWORK --sport $PORTS -j $NAME
	else
            # Send packets going to $PORTS httpd to the $NAME chain
	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL --dport $PORTS -j $NAME
	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL --sport $PORTS -j $NAME
	fi
    elif [ ! -z "$NETWORK" ]; then
            # Send packets going to $PORT httpd to the $NAME chain
	    echo $IPTABLES -A OUTPUT -t security -d $NETWORK -j $NAME
	    echo $IPTABLES -A INPUT -t security -s $NETWORK -j $NAME
    else
	echo $IPTABLES -A OUTPUT -t security -j $NAME
	echo $IPTABLES -A INPUT -t security -j $NAME
    fi
  }
  usage() {
      	 $"""
  Usage: $0 -i
  Usage: $0 -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
  Usage: $0 -f NAME
  """
  }

  echo
  echo "#---------------"
  echo "# $0 $*"
  echo "#---------------"
  echo
  IPTABLES=iptables
  NAME=
  PORTS=
  MCS=s0
  NETWORK=
  TYPE=client_packet_t
  PROTOCOL=tcp
  FINISH=0
  START=0
  INIT=0

  while getopts "sfin:p:m:t:T:P:" i; do
    case "$i" in
	i)
	    INIT=1
	    ;;
	s)
	    START=1
	    ;;
	f)
	    FINISH=1
	    ;;
	P)
	    PROTOCOL=$OPTARG
	    ;;
	T)
	    IPTABLES=$OPTARG
	    ;;
	n)
	    export NETWORK=$OPTARG
	    ;;
	t)
	    export TYPE=$OPTARG
	    ;;
	p)
	    export PORTS=$OPTARG
	    ;;
	m)
	    export MCS=$OPTARG
	    ;;
	*)
	    usage
	    exit 1
  esac
  done

  # Init does not require a NAME
  if [ $INIT == 1 ]; then 
    init
    exit $?
  fi

  # Move out processed options from arguments
  shift $(( OPTIND - 1 ))

  NAME=$1

  if [ -z "$NAME" -o -z "$MCS" -o -z "$NAME" ]; then
	usage
	exit 1
  fi

  if [ $START == 1 ]; then 
    start
    exit $?
  fi

  if [ $FINISH == 1 ]; then 
    fini
    exit $?
  fi

  setup_network


Скрипт можно запускать со следующими параметрами:

Инициализируем secmark-метки:
   ./secmarkgen -i

Определяем имя сети (имя Iptables-цепочки):
   ./secmarkgen -s INTERNAL


Привязываем к созданной цепочке набор правил. Синтаксис команды:
   ./secmarkgen -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME

Например:

   ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL

Для завершения формирования secmark-правил и их привязки к определенной
SELinux-метке используется команда:

   ./secmarkgen -f NAME

Например, 

   ./secmarkgen -f -t internal_packet_t INTERNAL

в итоге будет сгенерирован примерно такой скрипт:

   #--------------------
   # ./secmarkgen -i
   #--------------------
   iptables -F -t security

   iptables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore

   iptables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore

   #--------------------
   # ./secmarkgen -s INTERNAL
   #--------------------

   iptables -t security -X INTERNAL 2> /dev/null

   iptables -t security -N INTERNAL

   #--------------------
   # ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
   #--------------------

   iptables -A OUTPUT -t security -d 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL

   iptables -A INPUT -t security -s 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL

   #--------------------
   # ./secmarkgen -f -t internal_packet_t INTERNAL
   #--------------------

   iptables -t security -A INTERNAL -j SECMARK --selctx system_u:object_r:internal_packet_t:s0

   iptables -t security -A INTERNAL -j CONNSECMARK --save

   iptables -t security -A INTERNAL -j ACCEPT


Для генерации iptables-правил для локальных приложений используется примерно
такой скрипт (secmark_test.sh):

   ./secmarkgen -i
   ./secmarkgen -s INTERNAL
   ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
   ./secmarkgen -f -t internal_packet_t INTERNAL
   ./secmarkgen -s DNS
   ./secmarkgen -P udp -p 53 DNS
   ./secmarkgen -P tcp -p 53 DNS
   ./secmarkgen -f -t dns_external_packet_t DNS
   ./secmarkgen -s EXTERNAL
   ./secmarkgen EXTERNAL
   ./secmarkgen -f -t external_packet_t EXTERNAL
   ./secmarkgen -T ip6tables -i
   ./secmarkgen -T ip6tables -s INTERNAL
   ./secmarkgen -T ip6tables -n FEC0::/10,::1/128,FF::/8,FE80::/10FC00::/7 INTERNAL
   ./secmarkgen -T ip6tables -f -t internal_packet_t INTERNAL
   ./secmarkgen -T ip6tables -s EXTERNAL
   ./secmarkgen -T ip6tables EXTERNAL
   ./secmarkgen -T ip6tables -f -t external_packet_t EXTERNAL
   
Генерируем соответствующие iptables-правила:

   ./secmark_test.sh > /tmp/rules

Устанавливать данные iptables-правила пока рано, вначале нужно определить
соответствующие указанным меткам (*_packet_t) SELinux-политики, без которых
использование данных меток в iptables приведет к выводу ошибки.

Формируем файл с SELinux-политиками (secmark.te):

   policy_module(secmark, 1.0)

   gen_require('

      attribute domain;

      attribute sysadm_usertype;

      # Domains that a staff user could transition to

      attribute staff_usertype;

      attribute telepathy_domain;

      type ping_t;

      type vpnc_t;

      type ssh_t;
  
      type nsplugin_t;

      type mozilla_plugin_t;

      # System domains that want to talk to the external network

      type ntpd_t;

      type sssd_t;

   ')

   # Type Definitions

   attribute external_packet;

   type internal_packet_t;

   corenet_packet(internal_packet_t)

   type dns_external_packet_t, external_packet;

   corenet_packet(dns_external_packet_t)

   type external_packet_t, external_packet;

   corenet_packet(external_packet_t)

   # Allow Rules

   allow domain internal_packet_t:packet { recv send };

   allow sysadm_usertype external_packet:packet { recv send };

   allow staff_usertype external_packet:packet { recv send };

   allow vpnc_t external_packet:packet { recv send };

   allow ssh_t external_packet:packet { recv send };

   allow mozilla_plugin_t external_packet:packet { recv send };

   allow nsplugin_t external_packet:packet { recv send };

   allow telepathy_domain external_packet:packet { recv send };

   allow ping_t external_packet:packet { recv send };

   allow ntpd_t external_packet:packet { recv send };

   dontaudit sssd_t dns_external_packet_t:packet { recv send };


Рассмотрим правила более подробно.
Строка

   policy_module(secmark, 1.0)

определяет имя модуля с политиками. 

Далее следует список требований

   gen_require('

      attribute domain;
      ... 
      type sssd_t;
   ')

При написании SELinux-политики необходимо сослаться на все типы и атрибуты,
чтобы их можно было использовать в правилах. Подобные ссылки указываются в
блоке gen_requires. Одновременно можно определить новые типы. Если один из
определенных в gen_requires атрибутов или типов будет не определен в других
частях правил, SELinux не активирует созданную политику. Например, атрибут
staff_usertype предоставляется всем обслуживающим пользовательским процессам,
sysadm_usertype присваивается всем процессам, используемым при
администрировании, домен telepathy_domain охватывает все приложения, связанные
с фреймворком telepathy.

Далее, в файле следуют правила определения типов и групп. Создаем атрибут
external_packet для группировки всех  правил, связанных с внешним трафиком.
Также создаем интерфейс corenet_packet для ассоциации набора правил с пакетами.

   attribute external_packet;
   type internal_packet_t;
   corenet_packet(internal_packet_t)
   type dns_external_packet_t, external_packet;
   corenet_packet(dns_external_packet_t)
   type external_packet_t, external_packet;
   corenet_packet(external_packet_t)
  

Далее указано правило, разрешающее всем процессам отправку и прием внутренних
пакетов из локальной сети:

   allow domain internal_packet_t:packet { recv send };

Следующее правило позволяет запускаемым администраторами программам отправлять
и принимать пакеты из внешних сетей (вместо указания  xternal_packet_t в
правиле фигурирует атрибут external_packet, который позволяет провести действие
сразу над группой -  external_packet_t и dns_external_packet_t):


   allow sysadm_usertype external_packet:packet { recv send };
   allow staff_usertype external_packet:packet { recv send };
   allow vpnc_t external_packet:packet { recv send };
   allow ssh_t external_packet:packet { recv send };
   allow mozilla_plugin_t external_packet:packet { recv send };
   allow nsplugin_t external_packet:packet { recv send };
   allow telepathy_domain external_packet:packet { recv send };
   allow ping_t external_packet:packet { recv send };

Для сервиса ntpd заведен отдельный тип ntp_external_packet_t:

   allow ntpd_t external_packet:packet { recv send };

Для программы sssd запрещаем общение с системами за пределами приватной сети:

   dontaudit sssd_t dns_external_packet_t:packet { recv send };




Теперь приступим к компиляции, установке и применению созданной SELinux-политики:

Компилируем:

   make -f /usr/share/selinux/devel/Makefile

Устанавливаем:

   semodule -i secmark.pp

Активируем iptables-правила:

   sh /tmp/rules

Сохраняем внесенные изменения:

   service iptables save
   service ip6tables save

С этого момента каждому сетевому пакету присваивается одна из трех созданных
SELinux-меток. Для отладки следует проследить за появлением avc-сообщений и при
необходимости добавить исключения с использованием правил allow/dontaudit или
расследовать причину появления непрошеного трафика.
 
31.03.2011 , Источник: http://www.linux.com/learn/tutorial...
Ключи: selinux, iptables, policy, firewall, limit, linux / Лицензия: CC-BY
Раздел:    Корень / Безопасность / Шифрование, PGP

Обсуждение [ RSS ]
 
  • 1, yurii, 03:13, 01/04/2011 [ответить] [смотреть все]
  • +/
    всё круто, вот только автор не поленился бы пройтись по "переводу" прежде чем постить ...
     
  • 2, hostmaster, 11:57, 04/04/2011 [ответить] [смотреть все]
  • +/
    совершенно зря опущено описание use case где автор рассказывает зачем он это делает.
     
  • 3, crypt, 21:59, 19/04/2011 [ответить] [смотреть все]
  • +/
    >"Всем программ, запущенные в рамках сессии

    пользователя, разрешено обращаться как ко внутренним, так и к внешним сетевым ресурсам."

    Т.е. малваре запущенное во время сеанса пользователя будет иметь доступ в Интеренет? А смысл тогда этого всего? От чего хотел обезопасить себя автор???

     

    Ваш комментарий
    Имя:         
    E-Mail:      
    Заголовок:
    Текст:



      Закладки на сайте
      Проследить за страницей
    Created 1996-2017 by Maxim Chirkov  
    ДобавитьРекламаВебмастеруГИД  
    Hosting by Ihor