iptables에 플래그가 지정되었지만 예외로 라우팅되지 않는 이유는 무엇입니까?

iptables에 플래그가 지정되었지만 예외로 라우팅되지 않는 이유는 무엇입니까?

도메인 이름을 사용하여 브라우저의 라우팅 패킷을 제어하여 특수 도메인 이름 내의 트래픽 패킷이 VPN을 통과하고 특수 도메인 이름이 없는 다른 트래픽 패킷이 일반 라우팅을 통과하도록 하고 싶습니다. 저는 dnsmasq와 iptables를 사용하여 이를 달성했습니다.

그런데 저는 dnsmasq와 wireguard가 포함된 노트북(deepinLinux 4.15.0-29deepin-generic)을 사용하고 있습니다. 제 노트북은 VPN 클라이언트이자 DNS 서버이기도 합니다.

다음과 같이 진행하세요:

1DNSmasq 구성

구성 파일:

root@notebook-PC:~# cat /etc/dnsmasq.conf
# auto-generated config file from /etc/config/dhcp
conf-file=/etc/dnsmasq.conf
domain-needed
log-queries
log-facility=/var/log/dnsmasq.log
no-resolv
localise-queries
read-ethers
bogus-priv
expand-hosts
local-service
cache-size=150
domain=lan
server=/lan/
server=223.6.6.6
# dhcp-leasefile=/tmp/dhcp.leases
# addn-hosts=/tmp/hosts
conf-dir=/etc/dnsmasq.d
stop-dns-rebind
rebind-localhost-ok
dhcp-broadcast=tag:needs-broadcast


dhcp-range=lan,192.168.10.100,192.168.10.249,255.255.255.0,12h
# no-dhcp-interface=eth0.2

그리고 /etc/dnsmasq.d에는 파일이 하나만 있습니다.

root@notebook-PC:~# cd /etc/dnsmasq.d/
root@notebook-PC:/etc/dnsmasq.d# more newgfw.conf 
# dnsmasq rules generated by ss_spec_dst_fw
# Last Updated on 2019-04-29 13:36:58
# 
server=/030buy.com/8.8.8.8#53
ipset=/030buy.com/ss_spec_dst_fw
server=/0rz.tw/8.8.8.8#53
ipset=/0rz.tw/ss_spec_dst_fw
server=/1000giri.net/8.8.8.8#53
ipset=/1000giri.net/ss_spec_dst_fw
...........

"server" 및 "ipset" 옵션은 이러한 dns가 8.8.8.8을 쿼리하도록 한 다음 응답 호스트 IP를 ipset ss_spec_dst_fw에 추가합니다.

물론 dnsmasq를 DNS 서버로 추가하는 것을 잊지 않았습니다.

root@notebook-PC:~# nslookup
> google.com
Server:     127.0.0.1
Address:    127.0.0.1#53

Non-authoritative answer:
Name:   google.com
Address: 172.217.24.206
Name:   google.com
Address: 2404:6800:4005:806::200e
> 

2wg-quick을 수정하고 wireguard를 시작하세요

모든 트래픽이 VPN 인터페이스를 통과하도록 하는 wg-quick.sh를 찾은 다음 규칙을 직접 추가하고 싶은 3줄의 코드를 주석 처리했습니다.

vi /usr/bin/wg-quick

................
add_default() {
    local table proto key value
    if ! get_fwmark table; then
        table=51820
        while [[ -n $(ip -4 route show table $table) || -n $(ip -6 route show table $table) ]]; do
            ((table++))
        done
        cmd wg set "$INTERFACE" fwmark $table
    fi
    proto=-4
    [[ $1 == *:* ]] && proto=-6
#   cmd ip $proto route add "$1" dev "$INTERFACE" table $table
#   cmd ip $proto rule add not fwmark $table table $table
#   cmd ip $proto rule add table main suppress_prefixlength 0
    while read -r key _ value; do
        [[ $value -eq 1 ]] && sysctl -q "$key=2"
    done < <(sysctl -a -r '^net\.ipv4.conf\.[^ .=]+\.rp_filter$')
    return 0
}
................

그런 다음 와이어가드가 시작되면

wg-quick up wgnet0

wgnet0: flags=209<UP,POINTOPOINT,RUNNING,NOARP>  mtu 1420
        inet 192.168.32.2  netmask 255.255.255.0  destination 192.168.32.2
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 1000  (UNSPEC)
        RX packets 15  bytes 1380 (1.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 615  bytes 21652 (21.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlp5s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.3  netmask 255.255.255.0  broadcast 192.168.1.255

wgnet0은 특수 도메인 이름 트래픽을 통해 사용되는 VPN 인터페이스이고, wlp5s0은 일반 트래픽을 통해 사용되는 공용 인터페이스입니다.

ip rule show follow

root@notebook-PC:~# ip rule
0:  from all lookup local 
220:    from all lookup 220 
32766:  from all lookup main 
32767:  from all lookup default 

[3]규칙 및 라우팅 구성

/etc/iproute2/rt_tables 파일에 wg 테이블을 추가합니다.

root@notebook-PC:~# cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
201     wg
0   unspec
#
# local
#
#1  inr.ruhep

그런 다음 다음과 같이 규칙을 추가하십시오.

ip -4 route add table wg default via 192.168.32.1 dev wgnet0 metric 100
ip rule add prio 100 from all fwmark 51820 lookup wg

root@notebook-PC:~# ip rule show all
0:  from all lookup local 
100:    from all fwmark 0xca6c lookup wg 
220:    from all lookup 220 
32766:  from all lookup main 
32767:  from all lookup default 
root@notebook-PC:~# ip route show table wg
default via 192.168.32.1 dev wgnet0 metric 100 

[4] 태그 활성화

root@notebook-PC:~# cat /proc/sys/net/ipv4/tcp_fwmark_accept 
0
root@notebook-PC:~# sysctl -w net.ipv4.tcp_fwmark_accept=1
net.ipv4.tcp_fwmark_accept = 1
root@notebook-PC:~# cat /proc/sys/net/ipv4/tcp_fwmark_accept 
1

[5] 체인과 규칙을 추가하기 위해 iptables 구성

이전 단계의 결과로 VPN 인터페이스로 라우팅되어야 하는 ipset ss_spec_dst_fw에 IP를 추가한 다음 이러한 패킷을 표시해야 합니다.

이것으로기사(http://www.faqs.org/docs/iptables/traversingoftables.html), iptables는 두 단계로 라우팅 결정을 내립니다. 로컬 프로세스(이 경우 내 노트북의 브라우저 프로세스)는 OUTPUT 프로세스에 들어가기 전에 라우팅 결정을 내린 다음 다시 라우팅하려면 로컬 프로세스가 필요합니다.

그래서 제가 한 방법에 따라 OUTPUT_direct 체인에 규칙을 추가하고, ipset ss_spec_dst_fw와 일치하는 모든 패킷은 PREROUTING_direct 체인으로 점프하고, PREROUTING_direct 체인에 규칙을 추가하고, ipset ss_spec_dst_fw와 일치하는 모든 패킷은 아래 그림과 같이 표시되었습니다. 보여주다:

영상

PREROUTING_direct chain()이 ACCEPT 패킷으로 사용되면 다음과 같이 라우팅 결정이 다시 내려집니다.

root@notebook-PC:~# iptables -t mangle -A OUTPUT_direct -m set --match-set ss_spec_dst_fw dsts -j PREROUTING_direct

root@notebook-PC:~# iptables -t mangle -A PREROUTING_direct -j CONNMARK --restore-mark
root@notebook-PC:~# iptables -t mangle -A PREROUTING_direct -m set --match-set ss_spec_dst_fw dsts -j MARK --set-mark 51820
root@notebook-PC:~# iptables -t mangle -A PREROUTING_direct -j CONNMARK --save-mark
root@notebook-PC:~# iptables -t mangle -A PREROUTING_direct -j ACCEPT
root@notebook-PC:~# 
root@notebook-PC:~# iptables -L -t mangle
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
PREROUTING_direct  all  --  anywhere             anywhere            
PREROUTING_ZONES_SOURCE  all  --  anywhere             anywhere            
PREROUTING_ZONES  all  --  anywhere             anywhere            

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
INPUT_direct  all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
FORWARD_direct  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
OUTPUT_direct  all  --  anywhere             anywhere            

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
POSTROUTING_direct  all  --  anywhere             anywhere            

Chain FORWARD_direct (1 references)
target     prot opt source               destination         

Chain INPUT_direct (1 references)
target     prot opt source               destination         

Chain OUTPUT_direct (1 references)
target     prot opt source               destination         
PREROUTING_direct  all  --  anywhere             anywhere             match-set ss_spec_dst_fw dst

Chain POSTROUTING_direct (1 references)
target     prot opt source               destination         

Chain PREROUTING_ZONES (1 references)
target     prot opt source               destination         
PRE_public  all  --  anywhere             anywhere            [goto] 
PRE_public  all  --  anywhere             anywhere            [goto] 

Chain PREROUTING_ZONES_SOURCE (1 references)
target     prot opt source               destination         

Chain PREROUTING_direct (2 references)
target     prot opt source               destination         
CONNMARK   all  --  anywhere             anywhere             CONNMARK restore
MARK       all  --  anywhere             anywhere             match-set ss_spec_dst_fw dst MARK set 0xca6c
CONNMARK   all  --  anywhere             anywhere             CONNMARK save
ACCEPT     all  --  anywhere             anywhere            

Chain PRE_public (2 references)
target     prot opt source               destination         
PRE_public_log  all  --  anywhere             anywhere            
PRE_public_deny  all  --  anywhere             anywhere            
PRE_public_allow  all  --  anywhere             anywhere            

Chain PRE_public_allow (1 references)
target     prot opt source               destination         

Chain PRE_public_deny (1 references)
target     prot opt source               destination         

Chain PRE_public_log (1 references)
target     prot opt source               destination         
root@notebook-PC:~# 

이제 모든 작업이 완료되었지만 결과는 내 것이 아닙니다. 단, 작동하지 않습니다!

ipset ss_spec_dst_fw는 DNS 쿼리의 IP 응답을 추가했습니다.

root@notebook-PC:~# ipset list ss_spec_dst_fw
Name: ss_spec_dst_fw
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 5368
References: 2
Number of entries: 113
Members:
216.58.221.229
172.217.161.170
172.217.161.173
203.208.43.95
216.58.199.5
216.58.221.234
216.58.199.110
172.217.161.141
172.217.161.133
216.58.200.74
172.217.161.138
203.208.39.215
...........

dnsmasq가 제대로 작동하면 다음 IP 경로를 테스트합니다.

root@notebook-PC:~# ip route get 216.58.221.229
216.58.221.229 via 192.168.1.1 dev wlp5s0 src 192.168.1.3 uid 0 
    cache 

이 결과는 제가 예상한 것과 다릅니다. 192.168.1.1은 VPN 게이트웨이가 아닌 일반 게이트웨이입니다. 그런 다음 태그 51820(위 코드의 태그 값)을 추가하여 테스트합니다.

root@notebook-PC:~# ip route flush cache

root@notebook-PC:~# ip route get 216.58.221.229 mark 51820
216.58.221.229 via 192.168.32.1 dev wgnet0 table wg src 192.168.32.2 mark 0xca6c uid 0 
    cache 
root@notebook-PC:~# ip route flush cache
root@notebook-PC:~# ip route get 216.58.221.229
216.58.221.229 via 192.168.1.1 dev wlp5s0 src 192.168.1.3 uid 0 
    cache 

이 결과는 IP 규칙과 경로가 정상인지 확인하지만 그렇지 않은 경우 iptables가 이러한 패킷을 표시하는지 확인하고 경로 216.58.221.229를 추적하고 로그를 기록합니다.

root@notebook-PC:~# traceroute 216.58.221.229
traceroute to 216.58.221.229 (216.58.221.229), 30 hops max, 60 byte packets
 1  * * *
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  *

추적 로그를 연결합니다.

root@notebook-PC:~# conntrack -E -d 216.58.221.229
    [NEW] udp      17 30 src=192.168.1.3 dst=216.58.221.229 sport=44951 dport=33434 [UNREPLIED] src=216.58.221.229 dst=192.168.1.3 sport=33434 dport=44951 mark=51820
    [NEW] udp      17 30 src=192.168.1.3 dst=216.58.221.229 sport=34181 dport=33435 [UNREPLIED] src=216.58.221.229 dst=192.168.1.3 sport=33435 dport=34181 mark=51820
    [NEW] udp      17 30 src=192.168.1.3 dst=216.58.221.229 sport=58059 dport=33436 [UNREPLIED] src=216.58.221.229 dst=192.168.1.3 sport=33436 dport=58059 mark=51820
    [NEW] udp      17 30 src=192.168.1.3 dst=216.58.221.229 sport=40739 dport=33437 [UNREPLIED] src=216.58.221.229 dst=192.168.1.3 sport=33437 dport=40739 mark=51820
........................

마크 51820 완료!

이제 혼란스러워요. 내가 무엇을 놓쳤나요?

답변1

mangle/PREROUTING로컬에서 시작된 패킷은 체인을 통해 전달 되지 않습니다 . 태그 지정 규칙을 mangle/OUTPUT체인으로 이동해야 합니다 . " iptables-save -c" 또는 " "를 사용하여 iptables -L -n -v규칙 세트를 나열하고(첫 번째 명령은 전체 규칙 세트를 표시하므로 더 좋습니다) 규칙 카운터를 확인할 수 있습니다. 귀하의 경우 카운터는 0일 수 있습니다.

관련 정보