Анонимайзер на основе GRE в Linux

Зачем?

Обратился однажды ко мне мой старый товарищ с проблемой, что вот некие буржуйские ресурсы не пущают советского человека к заморским радостям. При этом не помогают в борьбе с супостатом не VPN не анонимайзеры не прочие руны и мантры. Как оказывается, стали нынче блокировать уже не только по IP и его расовой принадлежности, но и заглядывать гораздо глубже, вплоть до MTU! Ситуация была критической и нужно было с этим что то делать…

Задача

Стояла достаточно понятная задача, перенести десктоп пользователя де-юре в страну, в которой проживает ресурс «жадина» и прикинуться местным аборигеном. В свете используемых ухищрений со стороны супостата, решение было только одно — прозрачный тоннель с человеческим MTU и дефолтным маршрутом на десктопе. В связи с тем, что товарищ был «православным» и юзал во весь рост линь, решение стало очевидным.

Рецепт

Для реализации поставленной задачи, в искомой стране арендуется VPS сервер с минимальными требованиями ну и естественно белым и пушистым IP адресом для организации маршрутизатора. На стороне клиента тоже должен быть выделенный IP, иначе GRE не работает.

Cхема взаимодействия
Cхема взаимодействия

Далее на клиенте и на роутере необходимо запустить из произвольной директории соответствующие скрипты (естественно от root’a), которые приведены ниже и сконфигурировать тоннель. Для запуска скриптов, необходимо скопировать контент в файл и сделать его исполняемым. Скрипты писались и проверялись под Debian, соответственно работоспособность на иных осях не гарантирую.

1
2
3
4
5
6
7
8
# Создаём файл. 
grevm$ touch grerouter.sh
# Открываем на редактирование и вставляем скопированный скрипт. Сохраняем, выходим. 
grevm$ nano grerouter.sh
# Делаем файл исполняемым.
grevm$ chmod +x grerouter.sh
# Выполняем скрипт.
grevm$ sh grerouter.sh
1
2
3
4
5
6
7
8
# Создаём файл. 
grecl$ touch greclient.sh
# Открываем на редактирование и вставляем скопированный скрипт. Сохраняем, выходим. 
grecl$ nano greclient.sh
# Делаем файл исполняемым.
grecl$ chmod +x greclient.sh
# Выполняем скрипт.
grecl$ sh greclient.sh

Настройка маршрутизатора

После выполнения скрипта, на нашем маршрутизаторе появляется конфигурационный файл /etc/grerouter/grerouter.conf, который нам необходимо заполнить.

1
2
3
4
5
6
7
# Здесь перечисляем через пробел или запятую IP адреса всех клиентов, которые будут подключаться к нашему роутеру. 
REMOTE="x.x.x.x x.x.x.x"
# Если ВМ имеет несколько адресов, то указываем с какого отправлять трафик. 
PUBLICK=""
# Указываем на каких портах пускать SSH и VNC.
RSSH="22"
RVNC="5901"

Теперь сохраняем файл и запускаем маршрутизатор любым из перечисленных ниже способов.

1
grevm$ service grerouter start
1
grevm$ /etc/init.d/grerouter start

После успешного старта переходим к конфигурации клиентов.

Настройка клиента

После выполнения скрипта, на нашем клиенте появляется конфигурационный файл /etc/greclient/greclient.conf, который нам необходимо заполнить.

1
2
3
4
5
6
7
8
9
# Здесь указываем IP адрес нашего роутера. 
REMOTE="x.x.x.x"
# Указываем желаемый адрес для клиента. Если клиент является первым из списка перечисленных в роутере,
# то его сеть 192.168.0.x, если вторым, то 192.168.1.х и так далее.
LOCALIP="192.168.x.2"
# Адрес маршрутизатора из той-же сети. Он всегда первый. 
LOCALGW="192.168.x.1"
# Указание конкретного интерфейса через который ходить (не обязательно). 
IFNM=""

Теперь сохраняем файл и запускаем клиент любым из перечисленных ниже способов.

1
grecl$ service greclient start
1
grecl$ /etc/init.d/greclient start

После всех манипуляций можно сделать на клиенте трассировку и убедится что всё работает корректно. Вот собственно и всё! Управление происходит стандартными командами start|stop|restart|status

1
2
3
4
grecl$ /etc/init.d/greclient start
grecl$ /etc/init.d/greclient stop
grecl$ /etc/init.d/greclient restart
grecl$ /etc/init.d/greclient status

или

1
2
3
4
grevm$ service grerouter start
grevm$ service grerouter stop
grevm$ service grerouter restart
grevm$ service grerouter status

Как понять что всё работает?

В этой задаче поможет команда status

1
2
3
4
5
6
7
8
9
10
grevm$ service grerouter status
● grerouter.service - LSB: Start daemon at boot time
   Loaded: loaded (/etc/init.d/grerouter)
   Active: active (exited) since Сб 2017-10-14 17:05:23 MSK; 1min 12s ago
  Process: 12445 ExecStart=/etc/init.d/grerouter start (code=exited, status=0/SUCCESS)
 
окт 14 17:05:23 grevm systemd[1]: Started LSB: Start daemon at boot time.
окт 14 17:05:23 grevm grerouter[12445]: start grerouter at eth0:0 - xxx.xxx.xxx.xxx compleate
окт 14 17:05:23 grevm grerouter[12445]: Now running:
окт 14 17:05:23 grevm grerouter[12445]: 192.168.0.0	*	255.255.255.0 U	0	0	0 grel0

или

1
2
3
4
grevm$ /etc/init.d/grerouter status
status grerouter at eth0:0 - xxx.xxx.xxx.xxx 
Now running: 
192.168.0.0	*	255.255.255.0 U	0	0	0 grel0

Возможные «грабли»

1) Я писал это давно, и в момент изложения этой статьи что-то забыл;
2) У вашего домашнего провайдера или у хостера зарезан GRE трафик. Такое бывает, нужно позвонить ТП и провести разъяснительную беседу;
3) У вас на одной из сторон IP не выделенный а общественный, просто это тщательно скрывает ваш провайдер. Такое тоже бывает, нужно позвонить ТП и провести разъяснительную беседу с применением специальных «скриптов», возможно даже запрещённых.

З.Ы. Оставляйте свои комментарии по этому поводу, будем общаться 😉

Клиент

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#! /bin/bash
# /etc/init.d/
### BEGIN INIT INFO
# Provides:          greclient
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO
 
GSD=${0}
GSN=${0##*/}
CST=true
COM="compleate"
 
if [ ! -f /bin/sh ]; then
	ln -sf /bin/bash /bin/sh
fi
 
if [ ! -f /etc/init.d/greclient ]; then
	mkdir -p /etc/greclient
	touch /etc/greclient/greclient.conf
	echo -e "REMOTE=\"x.x.x.x\"\nLOCALIP=\"192.168.0.2\"\nLOCALGW=\"192.168.0.1\"\nIFNM=\"\"" > /etc/greclient/greclient.conf
	mv $GSD /etc/init.d/greclient
	chmod +x /etc/init.d/greclient
	update-rc.d greclient defaults
fi
 
source /etc/greclient/greclient.conf
 
if [ -z "$IFNM" ]; then
	DAR=$(ls /sys/class/net|awk '!/lo/&&!/gre/{print $0;exit}')
else
	DAR=$IFNM
fi
 
if [ -z "$REMOTE" ]; then
	echo "No REMOTE set"
	exit 1
fi
 
GIP=$(ifconfig $DAR | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
 
echo "$1 $GSN at $DAR - $GIP"
 
itf(){
	iptables -F
	iptables -X
	iptables -t nat -F
	iptables -t nat -X
	iptables -t mangle -F
	iptables -t mangle -X
	iptables -P INPUT ACCEPT
	iptables -P OUTPUT ACCEPT
	iptables -P FORWARD ACCEPT
}
 
stt(){
	if [ ! -f /var/lock/$GSN ] && [ -z $(route|grep gre)]; then
		CST=true
	else
		CST=false
	fi
}
 
sta(){
	stt
	echo "$1 $GSN at $DAR - $GIP $2"
	if [ "$CST" = true ]; then
		echo -e "\033[1;31mNow stopped\033[0m"
	else
		echo -e "\033[1mNow running:\033[0m \n\033[0;36m`route|grep gre`\033[0m"
	fi
}
 
srt(){
	stt
	if [ "$CST" = true ]; then
 
		GDR=$(route -n | grep 'UG[ \t]' | awk '{print $2}')
 
		ip tunnel add grel0 mode gre remote $REMOTE local $GIP
		ip addr add $LOCALIP/24 dev grel0
		ip link set grel0 up mtu 1500
 
		ip route add $REMOTE via $GDR
		ip route change default via $LOCALGW
 
		ip route flush table 200
		ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 200 $ROUTE ; done
		ip route add table 200 default via $LOCALGW
		ip rule add fwmark 200 table 200
		ip route flush cache
 
		$(itf)
 
		iptables -t mangle -A OUTPUT -o $DAR -p tcp --dport 0:49999 -s $GIP -j MARK --set-mark 200
		iptables -t mangle -A OUTPUT -o $DAR -p udp --dport 0:49999 -s $GIP -j MARK --set-mark 200
		iptables -t mangle -A OUTPUT -o $DAR -p tcp --dport 50000:65535 -s $GIP -j MARK --set-mark 200
		iptables -t mangle -A OUTPUT -o $DAR -p udp --dport 50000:65535 -s $GIP -j MARK --set-mark 200
 
		iptables -A PREROUTING -t nat -i grel0 -p tcp --sport 0:49999 -j DNAT --to $GIP
		iptables -A PREROUTING -t nat -i grel0 -p udp --sport 0:49999 -j DNAT --to $GIP
		iptables -A PREROUTING -t nat -i grel0 -p tcp --sport 50000:65535 -j DNAT --to $GIP
		iptables -A PREROUTING -t nat -i grel0 -p udp --sport 50000:65535 -j DNAT --to $GIP
 
		iptables -t nat -A POSTROUTING -o grel0 -j SNAT --to-source $LOCALIP
 
		iptables -A INPUT -i $DAR -p tcp --dport 0:49999 -j DROP
		iptables -A INPUT -i $DAR -p tcp --dport 50000:65535 -j DROP
		iptables -A INPUT -i $DAR -p udp --dport 0:49999 -j DROP
		iptables -A INPUT -i $DAR -p udp --dport 50000:65535 -j DROP
 
		iptables -A INPUT -p icmp --icmp-type echo-request -j REJECT
		iptables -A OUTPUT -p icmp --icmp-type echo-request -j REJECT
		iptables -A INPUT -p icmp --icmp-type echo-reply -j REJECT
		iptables -A OUTPUT -p icmp --icmp-type echo-reply -j REJECT
		iptables -A INPUT -p icmp --icmp-type 8 -j REJECT
		iptables -A OUTPUT -p icmp --icmp-type 8 -j REJECT
 
		iptables -I INPUT -p gre -s $REMOTE -j ACCEPT
 
		for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 0 > $f ; done
		echo 1 > /proc/sys/net/ipv4/ip_forward
		echo 0 > /proc/sys/net/ipv4/route/flush
		echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
 
		touch /var/lock/$GSN
	else
		exit 1
	fi
	sta $1 $2
}
 
stp(){
	stt
	if [ "$CST" = true ]; then
		exit 1
	else
		$(itf)
 
		GPR=$(route -n | grep 'UGH[ \t]' | awk '{print $2}')
 
		ip route change default via $GPR
		ip route delete $REMOTE via $GPR
 
		ip route flush table 200
		ip route flush cache
 
		ip link set grel0 down
		ip tunnel delete grel0
 
		echo 0 > /proc/sys/net/ipv4/ip_forward
		echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
 
		rm /var/lock/$GSN
	fi
	sta $1 $2
}
 
 
rst(){
	echo -e "\033[1mRestarting $GSN...\033[0m"
	stt
	if [ "$CST" = true ]; then
		echo -e "\033[1mAlready stopped. Now starting...\033[0m"
		srt "Starting" $2
	else
		echo -e "\033[1mStopping $GSN...\033[0m"
		while [ "$CST" = false ]; do
			stp "Stopping" $2
			echo -e "\033[1mWait a moment..\033[0m"
			sleep 1
			stt
			if [ "$CST" = true ]; then
				echo -e "\033[1mStopped successful. Now starting...\033[0m"
				srt "Starting" $2
				exit 0
			fi
		done
	fi
}
 
 
case "$1" in
	start)
		srt $1 $COM
		;;
	stop)
		stp $1 $COM
		;;
	restart)
		rst $1 $COM
		;;
	status)
		sta $1
		;;
	*)
		echo "Usage: /etc/init.d/$GSN {start|stop|restart|status}"
		exit 1
		;;
esac
 
exit 0

Маршрутизатор

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#! /bin/bash
# /etc/init.d/
### BEGIN INIT INFO
# Provides:          grerouter
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO
 
GSD=${0}
GSN=${0##*/}
CST=true
COM="compleate"
 
if [ ! -f /bin/sh ]; then
	ln -sf /bin/bash /bin/sh
fi
 
if [ ! -f /etc/init.d/grerouter ]; then
	mkdir -p /etc/grerouter
	touch /etc/grerouter/grerouter.conf
	echo -e "REMOTE=\"x.x.x.x x.x.x.x\"\nPUBLICK=\"\"\nRSSH=\"22\"\nRVNC=\"5901\"" > /etc/grerouter/grerouter.conf
	mv $GSD /etc/init.d/grerouter
	chmod +x /etc/init.d/grerouter
	update-rc.d grerouter defaults
fi
 
source /etc/grerouter/grerouter.conf
IFS=',|| ' read -ra arr <<< "$REMOTE"
 
if [ -z "$PUBLICK" ]; then
	DAR=$(ls /sys/class/net|awk '!/lo/&&!/gre/{print $0;exit}')
	GIP=$(ifconfig $DAR | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
else
	GIP=$PUBLICK
	DAR=$(netstat -ie|grep -B1 "$GIP"|head -n1|awk '{print $1}')
fi
 
if [ -z "$REMOTE" ]; then
	echo "No REMOTE set"
	exit 1
fi
 
 
itf(){
	iptables -F
	iptables -X
	iptables -t nat -F
	iptables -t nat -X
	iptables -t mangle -F
	iptables -t mangle -X
	iptables -P INPUT ACCEPT
	iptables -P OUTPUT ACCEPT
	iptables -P FORWARD ACCEPT
}
 
stt(){
	if [ ! -f /var/lock/$GSN ] && [ -z $(route|grep gre)]; then
		CST=true
	else
		CST=false
	fi
}
 
sta(){
	stt
	echo "$1 $GSN at $DAR - $GIP $2"
	if [ "$CST" = true ]; then
		echo -e "\033[1;31mNow stopped\033[0m"
	else
		echo -e "\033[1mNow running:\033[0m \n\033[0;36m`route|grep gre`\033[0m"
	fi
}
 
srt(){
	stt
	if [ "$CST" = true ]; then
		$(itf)
		iptables -t nat -A POSTROUTING -o ${DAR%:*} -j SNAT --to-source $GIP
 
		echo 1 > /proc/sys/net/ipv4/ip_forward
		echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
 
		for i in $(seq ${#arr[@]}); do
			p=$((i-1))
			if [ "$p" -lt "9" ]; then
				g="0$p"
				if [ "$p" -lt "99" ]; then
					g="0$g"
				fi
			fi
			iptables -I INPUT -p gre -s ${arr[$p]} -j ACCEPT
			iptables -t nat -A PREROUTING -p tcp --dport 5"$g"0 -j DNAT --to 192.168.$p.2:$RSSH
			iptables -t nat -A PREROUTING -p tcp --dport 5"$g"1 -j DNAT --to 192.168.$p.2:$RVNC
			ip tunnel add grel$p mode gre remote ${arr[$p]} local $GIP
			ip addr add 192.168.$p.1/24 dev grel$p
			ip link set grel$p up mtu 1500
		done
		touch /var/lock/$GSN
	else
		exit 1
	fi
	sta $1 $2
}
 
stp(){
	stt
	if [ "$CST" = true ]; then
		exit 1
	else
		$(itf)
 
		echo 0 > /proc/sys/net/ipv4/ip_forward
		echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
 
		for i in $(seq ${#arr[@]}); do
			p=$((i-1))
			ip link set grel$p down
			ip tunnel delete grel$p
		done
		rm /var/lock/$GSN
	fi
	sta $1 $2
}
 
 
rst(){
	echo -e "\033[1mRestarting $GSN...\033[0m"
	stt
	if [ "$CST" = true ]; then
		echo -e "\033[1mAlready stopped. Now starting...\033[0m"
		srt "Starting" $2
	else
		echo -e "\033[1mStopping $GSN...\033[0m"
		while [ "$CST" = false ]; do
			stp "Stopping" $2
			echo -e "\033[1mWait a moment..\033[0m"
			sleep 1
			stt
			if [ "$CST" = true ]; then
				echo -e "\033[1mStopped successful. Now starting...\033[0m"
				srt "Starting" $2
				exit 0
			fi
		done
	fi
}
 
 
case "$1" in
	start)
		srt $1 $COM
		;;
	stop)
		stp $1 $COM
		;;
	restart)
		rst $1 $COM
		;;
	status)
		sta $1
		;;
	*)
		echo "Usage: /etc/init.d/$GSN {start|stop|restart|status}"
		exit 1
		;;
esac
 
exit 0

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.