Как преобразовать вывод `iptables -S `в ширину -первый листинг

Solaris имеет привилегии, как описано здесь:https://docs.oracle.com/cd/E23824_01/html/821-1456/prbac-2.html. Как правило, привилегии назначаются ролям, а затем роли — пользователям, а внутри ролей вы можете назначать очень детализированные наборы привилегий исполняемым файлам и сценариям. Solaris RBAC на первый взгляд кажется похожим на sudo, однако на самом деле это своего рода противоположность, когда вы создаете детализированные наборы привилегий снизу вверх, в отличие от модели sudo, где вы пытаетесь ограничить привилегии сверху вниз.

Несмотря на то, что я давно пользуюсь OS X, я не знаю ни одного детализированногоcapabilities-такого механизма, который мог бы обеспечить аналогичную функцию регулирования привилегий пользователей и процессов. В зависимости от того, что вам нужно, вы можете использовать launchdдля повышения привилегий для (, например )демона. Однако я не знаю, насколько гранулированным вы можете быть.

2
06.04.2019, 07:40
2 ответа

Некоторое время назад мне нужно было сгладить -сначала дерево правил пользовательского брандмауэра и поместить их все в файл. Во всяком случае, не VyOS, а iptables. Я придумал следующий скрипт, посмотрите, поможет ли он вам.

Обратите внимание , что для этого скрипта требуется как минимум Bash v4

#!/bin/bash -

declare -A all_chains=()
declare -A queued_chains=()

builtin_chains_as_regexp='INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING'
queue_list=""
prepend_chain=""
show_chain_heading=false
one_go=false
uniquify=true

_print_usage() {
   cat <<- EOF
        Usage: $0 [-npofh] <starting-chain>

        -n    shows chain's creation command as heading, useful for spotting empty chains
        -p    prepends chain's name to each rule
        -o    read everything in one go, 10x quicker when many small chains
        -f    expand all references to a same chain, but beware of chain loops or chains referenced hundreds of times
        -h    shows this help
EOF
}

_expand_chain() {
    local chain_to_expand="${1}"

    local rules=""
    # if one_go selected, work with in-memory cache of chains
    if $one_go ; then
        rules="${all_chains[${chain_to_expand}]}"
    # otherwise read in chain to consider
    else
        rules="$(iptables -S "${chain_to_expand}")"
    fi

    $show_chain_heading && \
        ! [[ "${chain_to_expand}" =~ ${builtin_chains_as_regexp} ]] && \
        echo "-N ${chain_to_expand}"
    while read -r cmd chain rule ; do
        case "${cmd}" in
        -A)
            set -- ${rule}
            # look for target option in rule
            while [ -n "${1}" ] && ! [[ "${1}" =~ -(j|g) ]] ; do shift ; done
            # a few sanity checks
            [ -n "${1}" ] || continue # a rule with no target, skip it
            shift
            [ -n "${1}" ] || { echo "what!? empty target in ${rule}" >&2 ; continue ; }
            if [ -n "${all_chains[${1}]}" ] ; then
                # if target is a chain
                # add to queued chains if uniquify *not* requested or if chain never queued
                if ! $uniquify || [ -z "${queued_chains[${1}]}" ] ; then
                    queue_list+="${1} "
                    queued_chains[${1}]="1"
                fi
            fi
            # show rule
            echo "${prepend_chain:+[${chain_to_expand}] }${cmd} ${chain} ${rule}"
        ;;
        esac
    done <<<"${rules}"
}

###
# ACTUAL EXECUTION STARTS HERE
#

# parse command options if any
while getopts nphfo option ; do
    case $option in
    n) show_chain_heading=true
    ;;
    p) prepend_chain="1"
    ;;
    h) _print_usage ; exit 0
    ;;
    o) one_go=true
    ;;
    f) uniquify=false
    ;;
    '?') exit 1
    ;;
    esac
done

[ -n "${!OPTIND}" ] || { _print_usage ; exit 1 ; }

# preparation step:
# if one_go selected, slurp everything in
if $one_go ; then
    # invoke explicit command only when stdin is the terminal
    [ -t 0 ] && exec 0< <(iptables -S)
    while read -r cmd chain rule ; do
        case "${cmd}" in
        -N)
            all_chains[${chain}]=" " # <<-- whitespace to make provision for empty chains
        ;;
        -A)
            # assign rule to its chain in cache
            all_chains[${chain}]+=$'\n'"${cmd} ${chain} ${rule}"
        ;;
        esac
    done
# otherwise read in chain names only
else
    while IFS= read -r chain ; do
        all_chains[${chain}]="1"
    done < <(iptables -S | sed -ne '/^-N /s///p')
fi

# expand starting chain
_expand_chain ${!OPTIND}

# breadth-first expand queued chains
# as long as queue is not empty
while [ "${#queue_list}" -gt 0 ] ; do
    # take next queued chain
    subchain="${queue_list%% *}"
    # expand it
    _expand_chain "${subchain}"
    # remove expanded chain from queue
    queue_list="${queue_list#${subchain} }"
    # queue gets updated by _expand_chain as needed
done

exit 0

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

Если вы запустите его без параметров, он покажет сводку справки.

Обратите внимание, что по умолчанию каждая цепочка раскрывается только один раз, даже для цепочек, на которые ссылаются несколько раз. Вы можете запросить полностью сглаженный вывод -с опцией -f. Я сделал это так, потому что у меня была пара цепочек, на которые ссылались тысячи других цепочек, и сведение всего этого заняло бы часы (этот скрипт, конечно, не выполняет параллельную обработку ). Так что имейте это в виду, если у вас есть подобные настройки.

2
27.01.2020, 22:02

Вот моя интерпретация сортировки BFS на выходе iptables -S; он считывает каждое правило и находит целевую (или -Pполитику ); как только все правила прочитаны, он начинает со встроенных целей -и печатает последовательные уровни правил.

iptables -bfs.pl

#!/usr/bin/perl -w
use strict;

# for now, a chain name has to match regex: [[:alnum:]_-]+

my %jumpsto = ();

while (<>) {
  chomp;
  next if /^#/;
  if (/-[AIR]\s+([[:alnum:]_-]+).*-j\s+([[:alnum:]_-]+)/) {
        unless (exists $jumpsto{$1}{$2}) {
                $jumpsto{$1}{$2}=$_;
        }
  } elsif (/-P ([[:alnum:]_-]+)\s+(ACCEPT|DROP)/) {
        unless (exists $jumpsto{$1}{$2}) {
                $jumpsto{$1}{$2}=$_;
        }
  }
}

my @queue = ();
push @queue, qw(INPUT OUTPUT FORWARD PREROUTING POSTROUTING);
my @nextqueue = ();
while (@queue) {
  my $item = shift @queue;
  foreach my $target (keys %{ $jumpsto{$item} }) {
    print $jumpsto{$item}{$target}. "\n";
    push @nextqueue, $target;
  }
  if (! @queue && @nextqueue) {
    @queue = @nextqueue;
    @nextqueue = ();
    print "---------------\n";
  }
}

При вводе образца в вопрос вывод:

-A INPUT -j UBNT_VPN_IPSEC_FW_HOOK
-P INPUT ACCEPT
-A INPUT -j VYATTA_POST_FW_IN_HOOK
-A INPUT -j VYATTA_FW_LOCAL_HOOK
-P OUTPUT ACCEPT
-A OUTPUT -j VYATTA_POST_FW_OUT_HOOK
-A FORWARD -j VYATTA_FW_IN_HOOK
-A FORWARD -j MINIUPNPD
-P FORWARD ACCEPT
-A FORWARD -j VYATTA_POST_FW_FWD_HOOK
-A FORWARD -j UBNT_VPN_IPSEC_FW_IN_HOOK
-A FORWARD -j UBNT_FW_IN_SUSPEND_HOOK
-A FORWARD -j UBNT_PFOR_FW_HOOK
-A FORWARD -j VYATTA_FW_OUT_HOOK
---------------
-A VYATTA_POST_FW_IN_HOOK -j ACCEPT
-A VYATTA_FW_LOCAL_HOOK -i eth0 -j WAN_LOCAL
-A VYATTA_POST_FW_OUT_HOOK -j ACCEPT
-A VYATTA_FW_IN_HOOK -i eth1 -j LAN1_IN
-A VYATTA_FW_IN_HOOK -i eth0 -j WAN_IN
-A VYATTA_POST_FW_FWD_HOOK -j ACCEPT
-A VYATTA_FW_OUT_HOOK -o eth0 -j WAN_OUT
---------------
-A WAN_LOCAL -m comment --comment WAN_LOCAL-30 -m state --state INVALID -j DROP
-A WAN_LOCAL -m comment --comment WAN_LOCAL-10 -m state --state ESTABLISHED -j RETURN
-A WAN_LOCAL -m comment --comment WAN_LOCAL-30 -m state --state INVALID -j LOG --log-prefix "[WAN_LOCAL-30-D]"
-A LAN1_IN -p udp -m comment --comment LAN1_IN-20 -m udp --dport 53 -m set --match-set dnsaddr dst -j RETURN
-A LAN1_IN -m comment --comment LAN1_IN-10 -m state --state INVALID -j DROP
-A LAN1_IN -m comment --comment LAN1_IN-10 -m state --state INVALID -j LOG --log-prefix "[LAN1_IN-10-D]"
-A WAN_IN -m comment --comment WAN_IN-30 -m state --state INVALID -j DROP
-A WAN_IN -m comment --comment WAN_IN-10 -m state --state ESTABLISHED -j RETURN
-A WAN_IN -m comment --comment WAN_IN-30 -m state --state INVALID -j LOG --log-prefix "[WAN_IN-30-D]"
-A WAN_OUT -m comment --comment WAN_OUT-40 -m state --state INVALID -j DROP
-A WAN_OUT -m comment --comment WAN_OUT-10 -m state --state NEW -j RETURN
-A WAN_OUT -m comment --comment WAN_OUT-40 -m state --state INVALID -j LOG --log-prefix "[WAN_OUT-40-D]"
---------------

Моя первоначальная неверная интерпретация заключалась в следующем perl-скрипте, который преобразует iptables -Sв файл, совместимый с graphviz -. Он создает граф, который связывает исходные цепочки с их целевыми цепочками.

iptables -точка.pl

#!/usr/bin/perl -w
use strict;

# for now, a chain name has to match regex: [[:alnum:]_-]+

print "digraph rules {\n";
print "\toverlap=scalexy;\n";

my %jumpsto = ();

while (<>) {
  chomp;
  next if /^#/;
  if (/-[AIR]\s+([[:alnum:]_-]+).*-j\s+([[:alnum:]_-]+)/) {
        unless (exists $jumpsto{$1}{$2}) {
                print "\"$1\" -> \"$2\";\n";
                $jumpsto{$1}{$2}=1;
        }
  } elsif (/-P ([[:alnum:]_-]+)\s+(ACCEPT|DROP)/) {
        unless (exists $jumpsto{$1}{$2}) {
                print "\"$1\" -> \"$2\";\n";
                $jumpsto{$1}{$2}=1;
        }
  }
}

print "}\n";

Учитывая входные данные выборки в вопросе, результирующий результат будет:

digraph rules {
        overlap=scalexy;
"INPUT" -> "ACCEPT";
"FORWARD" -> "ACCEPT";
"OUTPUT" -> "ACCEPT";
"INPUT" -> "UBNT_VPN_IPSEC_FW_HOOK";
"INPUT" -> "VYATTA_FW_LOCAL_HOOK";
"INPUT" -> "VYATTA_POST_FW_IN_HOOK";
"FORWARD" -> "MINIUPNPD";
"FORWARD" -> "UBNT_VPN_IPSEC_FW_IN_HOOK";
"FORWARD" -> "UBNT_PFOR_FW_HOOK";
"FORWARD" -> "UBNT_FW_IN_SUSPEND_HOOK";
"FORWARD" -> "VYATTA_FW_IN_HOOK";
"FORWARD" -> "VYATTA_FW_OUT_HOOK";
"FORWARD" -> "VYATTA_POST_FW_FWD_HOOK";
"OUTPUT" -> "VYATTA_POST_FW_OUT_HOOK";
"LAN1_IN" -> "LOG";
"LAN1_IN" -> "DROP";
"LAN1_IN" -> "RETURN";
"VYATTA_FW_IN_HOOK" -> "WAN_IN";
"VYATTA_FW_IN_HOOK" -> "LAN1_IN";
"VYATTA_FW_LOCAL_HOOK" -> "WAN_LOCAL";
"VYATTA_FW_OUT_HOOK" -> "WAN_OUT";
"VYATTA_POST_FW_FWD_HOOK" -> "ACCEPT";
"VYATTA_POST_FW_IN_HOOK" -> "ACCEPT";
"VYATTA_POST_FW_OUT_HOOK" -> "ACCEPT";
"WAN_IN" -> "RETURN";
"WAN_IN" -> "LOG";
"WAN_IN" -> "DROP";
"WAN_LOCAL" -> "RETURN";
"WAN_LOCAL" -> "LOG";
"WAN_LOCAL" -> "DROP";
"WAN_OUT" -> "RETURN";
"WAN_OUT" -> "LOG";
"WAN_OUT" -> "DROP";
}

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

iptables chain targets

1
27.01.2020, 22:02

Теги

Похожие вопросы