내가 뭘 할까?

내가 뭘 할까?

iptables에서 nftables로 마이그레이션했는데 성가신 문제에 봉착했습니다. 이전 시스템에는 매일 일부 규칙을 삭제/추가하는 스크립트가 있었습니다. 위치에 따라 iptables 규칙을 쉽게 추가/제거할 수 있으며 이는 일정합니다.

이제 우리는 성가신 핸들을 갖게 되었습니다. 스크립트에서 규칙을 추가하면 동적 핸들 번호를 통해 할당됩니다. 먼저 해당 핸들 번호를 검색하여 규칙을 삭제할 수 있습니다. 문제는 동일한 규칙을 제거했다가 다시 추가하는 경우입니다. 그 이후에는 핸들 번호가 증가하므로 동일하지 않습니다. 그래서 기존 시스템과 같은 간단한 방법을 사용할 수 없습니다.

누구든지 이 문제를 해결할 수 있는 솔루션을 제공할 수 있습니까? 체인에는 최소 40개의 규칙이 있으며 동일한 규칙을 삭제하고 매일 몇 가지 규칙을 다시 추가하고 싶습니다. iptables를 사용하면 너무 쉽지만 지금은 간단한 해결책을 찾을 수 없습니다.

감사해요.

답변1

OP는 이런 종류의 규칙을 사용합니다, 이것은 대답의 기초로 예로 사용할 레이아웃입니다.

add rule ip nat postrouting oifname $inet_if ip saddr 172.xx.xx.xx counter snat to $inet_if_ip
add rule ip nat postrouting oifname $inet_if ip saddr 172.xx.xx.xx counter snat to $inet_if_ip

...등...

세트를 사용하다

nftables특징세트, 비슷하다IP 세트iptables와 짝을 이루지만 더 다양합니다.

그래서 인수분해가 가능해요규칙을 하나의 규칙으로 결합한 다음 규칙을 다시 건드리지 않고 연관된 컬렉션에서만 작동합니다. 컬렉션 요소에 대한 작업(삭제 포함)에는 규칙과 달리 해당 콘텐츠의 순서가 관련이 없고 따라서 해시 목록을 사용하여 커널 메모리에서 효율적으로 검색하고 재정렬할 수 있으므로 핸들이 필요하지 않습니다.

독립적으로 계산한다면스트림(예: 유지되는 역할이 counter중요합니다. 이를 위해서는 최신 도구가 필요합니다(최소 >= 0.9.1, 그러나 nftables >= 0.9.4가 권장됨, 참조).내 대답이 답변 끝에 있는 "오류"도 참조하세요.nftables아직 개발 중이므로 일부 기능은 버전에 따라 다릅니다.nftables또는 커널.

이 답변에는 nftables 0.9.6 0.9.8 이 사용되었습니다 . 이는 일부 구문 및 기능(예: JSON)에 영향을 미칠 수 있습니다.

따라서 이 규칙 세트 대신:

define inet_if = eth0
define inet_if_ip = 192.0.2.2

table ip nat        # for idempotency
delete table ip nat # for idempotency

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname $inet_if ip saddr 172.17.1.2 counter snat to $inet_if_ip
        oifname $inet_if ip saddr 172.17.1.3 counter snat to $inet_if_ip
    }
}

나중에 채울 수 있는 세트를 사용하는 것이 가능합니다(또는 직접 채울 수도 있습니다).

define inet_if = eth0
define inet_if_ip = 192.0.2.2

table ip nat
delete table ip nat

table ip nat {
    set curfewlist {
        type ipv4_addr
        counter        # optional
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname $inet_if ip saddr @curfewlist snat to $inet_if_ip
    }
}

그런 다음 컬렉션은 06:00에 crontab에 채워질 수 있습니다(이전 예제에 따름).

nft 'add element ip nat curfewlist { 172.17.1.2, 172.17.1.3 }'

23:00에 하나씩 삭제할 수 있습니다.

nft 'delete element ip nat curfewlist { 172.17.1.2 }'
nft 'delete element ip nat curfewlist { 172.17.1.3 }'

또는 한 번에 여러 요소를 사용할 수 있습니다.

nft 'delete element ip nat curfewlist { 172.17.1.2, 172.17.1.3 }'

아니면 간단히 플러시하세요.

nft flush set ip nat curfewlist

참고: a의 범위(네임스페이스라고도 함)놓다자체 테이블 내: 컬렉션은 다른 테이블에서 참조될 수 없지만 다음과 관련됩니다.iptables테이블은 하나의 후크 유형으로 제한되지 않습니다. 하나는 함께 할 수 있습니다아마도 그래야 할 것이다동일한 테이블에 여러 유형의 체인이 있으면 동일한 컬렉션을 재사용할 수 있습니다.필터규칙과모방이 아닌 규칙iptables'테이블당 하나의 후크 유형으로 제한됩니다.

meta hour경쟁을 이용하라

커널 >= 5.5의 경우 더 이상 아무것도 변경할 필요가 없습니다.meta hour이는 패킷 경로를 통해 확인할 수 있습니다. 개인규칙은 다음으로 대체될 수 있습니다.

meta hour 06:00-23:00 oifname $inet_if ip saddr @curfewlist snat to $inet_if_ip

그리고 컬렉션은 결코 채워지지 않습니다. 일 년에 두 번만 일광 절약 시간이 변경되는 동안 커널은 항상 UTC 시간을 사용하므로 규칙 세트를 다시 로드해야 합니다. 전체 규칙 세트는 다음과 같습니다.

define inet_if = eth0
define inet_if_ip = 192.0.2.2

table ip nat
delete table ip nat

table ip nat {
    set curfewlist {
        type ipv4_addr
        counter
        elements = { 172.17.1.2, 172.17.1.3 }
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        meta hour 06:00-23:00 oifname $inet_if ip saddr @curfewlist snat to $inet_if_ip
    }
}

참고: 커널 메모리에 저장된 시간별 간격은 UTC 시간대를 따르며 항상 24시간 모듈로 단일 연속 간격입니다. 현지 시간대에 따라 시간 표현을 다르게 읽을 수 있습니다. 예를 들어 다음 과 != "23:00"-"06:00"같습니다 ."06:00"-"23:00"


위의 내용이 결과를 단순화한다고 생각하지만 아래에서는 다른 방법으로 핸들을 해결하거나 사용하려고 시도하는 방법을 다루겠습니다.

조이스틱이 필요하지 않습니다.

위의 접근 방식이 사용 사례에 충분하지 않은 경우에도 사용자 체인의 모든 논리적 규칙을 이동하고 규칙 수준 대신 체인 수준에서 작업을 수행할 수 있습니다. 이것은 여기에 주어집니다:

define inet_if = eth0

table ip nat
delete table ip nat

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname $inet_if jump curfew
    }

    chain curfew { }
}

06:00에 다음 규칙 세트 섹션(예: )이 로드됩니다 nft -f curfew.nft.

define inet_if_ip = 192.0.2.2

flush chain ip nat curfew #for idempotency

table ip nat {
    chain curfew {
        ip saddr 172.17.1.2 counter snat to $inet_if_ip
        ip saddr 172.17.1.3 counter snat to $inet_if_ip
    }
}

23:00에 다음 명령을 실행하십시오.

nft flush chain ip nat curfew

컨트롤러를 계속 사용할 수 있는 다른 방법이 있나요?

이를 위해서는 단순히 스크립트를 사용하는 것이 아니라 어떤 방식으로든 스크립트를 사용해야 합니다.NFFT.

나중에 규칙을 식별하려면 덤프가 필요합니다.모두규칙을 연결합니다(예: 커널에서 사용자 모드로 이동). 이게 뭐야?nftables” 개발자들은 처음부터 피하려고 했어요.

특정 사용 사례에서 나중에 제거될 수 있는 규칙을 추가하려는 경우 나중에 핸들을 조회할 필요가 없도록 규칙을 추가할 때 핸들을 저장하세요.

--echo이 옵션을 사용하면 --handle핸들을 포함하여 방금 추가한 콘텐츠가 자동으로 표시됩니다( nft --handle monitor별도로 실행할 수도 있음). 이전 curfew.nft파일을 사용하면 다음이 제공됩니다(각 호출마다 핸들이 변경됨).

# nft --echo --handle -f curfew.nft 
add chain ip nat curfew # handle 2
add rule ip nat curfew ip saddr 172.17.1.2 counter packets 0 bytes 0 snat to 192.0.2.2 # handle 4
add rule ip nat curfew ip saddr 172.17.1.3 counter packets 0 bytes 0 snat to 192.0.2.2 # handle 5

따라서 합리적인 필터를 사용하여 다시 실행하십시오(이 특정 규칙 세트 섹션에 무엇이 추가되었는지 알면 더 쉬워집니다).

# nft --echo --handle -f curfew.nft | sed -n 's/^add rule.*# handle \(.*\)$/\1/p' | tee curfew-handles.txt
6
7

추가 규칙을 수동으로 연결하고 해당 핸들을 저장할 수 있습니다.

# nft --echo --handle add rule ip nat curfew ip saddr 172.17.1.4 snat to 192.0.2.2 | sed -n 's/^add rule.*# handle \(.*\)$/\1/p' | tee -a curfew-handles.txt
8

그런 다음 목록에서 핸들에 대한 모든 규칙을 제거합니다.

# for i in $(cat curfew-handles.txt); do printf 'delete rule ip nat curfew handle %d\n' $i; done | nft -f - && : > curfew-handles.txt

고쳐 쓰다:nftables >= 0.9.8 더 나은 JSON 지원

nftables지원하다JSON 출력, 그러나 버전 0.9.8 필요: nft --echo --handle --json add rule ...버전 0.9.6에서는 아무 것도 에코하지 않지만 0.9.8에서는 잘 작동합니다(여기서는 커널 5.10.x에서 테스트했습니다).

다음을 사용하여 방금 추가한 규칙 핸들을 검색하는 예jq. 추가 출력 주석 줄 자체는 JSON 출력이 아니므로 필터링해야 합니다.

# nft --echo --json add rule ip nat curfew ip saddr 172.17.1.4 snat to 192.0.2.2 | 
    grep -v '^#' | 
    jq '.nftables[].add.rule.handle'
40

nft monitor또는 규칙에 따라 체인 정보를 제공하면서 둘 다 사용하면 더 유용합니다.

nft --json monitor | 
    grep --line-buffered -v '^#' |
    jq -j '
        .add.rule |
            if . != null then
                (.handle, " ", .family, " ", .table, " ", .chain, "\n")
            else
                empty
            end'

위의 이전 규칙 명령을 실행할 때의 결과:

40 ip nat curfew

경고하다:

  • 일부 nftables 버전의 버그

    현재(v0.9.8) --echo --handle일부 완전한 규칙 세트를 사용하면 nft경고(이전 규칙 세트가 비어 있는 경우) 또는 충돌이 발생할 수 있습니다(예: counter세트에 최근 도입된 키워드로 인해 이러한 명령이 발생하거나 실행 중인 명령이 충돌한 것 같습니다 nft --handle monitor). 지금은 규칙만 추가하는 명령에 계속 사용하는 것이 가장 좋습니다.

답변2

이것은 작동합니다:

handle=$(nft list ruleset -a | grep "$your_rule" | grep "#" | awk '{print $NF}')
test -n "$handle" && nft delete rule filter output handle "$handle"
nft insert rule filter output position XX ...

답변3

내가 뭘 할까?

사용자 정의 양식이므로 매번 교체하세요. 단일 호출로 완료할 수 있는 경우 테이블 업데이트는 원자성입니다 nft.

따라서 내 프로그램의 규칙을 변경하고, 테이블을 재생성하고, nft.

답변4

요소 시간 초과는 필요한 솔루션을 제공할 수 있습니다. 컬렉션에 주소나 포트를 넣을 수 있으며 만료 후에는 컬렉션에서 자동으로 제거됩니다.

시간 초과는 시간, 분, 초 또는 2시간, 10분, 5초 등의 조합으로 지정할 수 있습니다.

nftables wiki의 예를 인용하면 다음과 같습니다.

% nft add table inet myfilter
% nft add set inet myfilter myset {type ipv4_addr\; flags timeout\; }
% nft add element inet myfilter myset {10.0.0.1 timeout 10s }

결과:

% nft list ruleset
table inet myfilter {
    set myset {
        type ipv4_addr
        flags timeout
        elements = { 10.0.0.1 timeout 10s expires 8s}
    }
}

원천:https://wiki.nftables.org/wiki-nftables/index.php/Element_timeouts

관련 정보