도메인 이름을 사용하여 브라우저의 라우팅 패킷을 제어하여 특수 도메인 이름 내의 트래픽 패킷이 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일 수 있습니다.