-
Notifications
You must be signed in to change notification settings - Fork 3
/
replaceLocalHostsFileAgainstGfw.sh
570 lines (514 loc) · 18.5 KB
/
replaceLocalHostsFileAgainstGfw.sh
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
#!/bin/bash
# Function description:
# Google Hosts File For Linux, a Linux shell script make you access Google easily! Run it directly and enjoy Google services.
#
# Usage:
# bash replaceLocalHostsFileAgainstGfw.sh
#
# Birth Time:
# 2016-04-22 10:04:43.895515929 +0800
#
# Author:
# Open Source Software written by 'Guodong Ding <[email protected]>'
# Blog: http://dgd2010.blog.51cto.com/
# Github: https://github.com/DingGuodong
#
# Public header
# =============================================================================================================================
# resolve links - $0 may be a symbolic link
# learn from apache-tomcat-6.x.xx/bin/catalina.sh
PRG="$0"
while [ -h "$PRG" ]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
# Get standard environment variables
PRGDIR=`dirname "$PRG"`
# echo color function, smarter, learn from lnmp.org lnmp install.sh
function echo_r (){
# Color red: Error, Failed
[ $# -ne 1 ] && return 1
echo -e "\033[31m$1\033[0m"
}
function echo_g (){
# Color green: Success
[ $# -ne 1 ] && return 1
echo -e "\033[32m$1\033[0m"
}
function echo_y (){
# Color yellow: Warning
[ $# -ne 1 ] && return 1
echo -e "\033[33m$1\033[0m"
}
function echo_b (){
# Color blue: Debug Level 1
[ $# -ne 1 ] && return 1
echo -e "\033[34m$1\033[0m"
}
function echo_p (){
# Color purple: Debug Level 2
[ $# -ne 1 ] && return 1
echo -e "\033[35m$1\033[0m"
}
function echo_c (){
# Color cyan: friendly prompt, Level 1
[ $# -ne 1 ] && return 1
echo -e "\033[36m$1\033[0m"
}
# end echo color function, smarter
WORKDIR="$PRGDIR"
# end public header
# =============================================================================================================================
USER="`id -un`"
LOGNAME="$USER"
if [ $UID -ne 0 ]; then
echo "WARNING: Running as a non-root user, \"$LOGNAME\". Functionality may be unavailable. Only root can use some commands or options"
fi
# Name: replaceLocalHostsFileAgainstGfw.sh
# Refer to: https://github.com/racaljk/hosts
# Backups: https://coding.net/u/scaffrey/p/hosts/git
# define user friendly messages
header="
Function: Execute this shell script to access Google, etc easily.
Open source software Written by Guodong Ding <[email protected]>.
Blog: http://dgd2010.blog.51cto.com/
Github: https://github.com/DingGuodong
Last updated: 2016-4-19
"
function check_network_connectivity(){
echo_b "checking network connectivity ... "
network_address_to_check=8.8.4.4
stable_network_address_to_check=114.114.114.114
ping_count=2
ping -c ${ping_count} ${network_address_to_check} >/dev/null
retval=$?
if [ ${retval} -ne 0 ] ; then
if ping -c ${ping_count} ${stable_network_address_to_check} >/dev/null;then
echo_g "Network to $stable_network_address_to_check succeed! "
echo_y "Note: network to $network_address_to_check failed once! maybe just some packages loss."
elif ! ip route | grep default >/dev/null; then
echo_r "Network is unreachable, gateway is not set."
exit 1
elif ! ping -c2 $(ip route | awk '/default/ {print $3}') >/dev/null; then
echo_r "Network is unreachable, gateway is unreachable."
exit 1
else
echo_r "Network is blocked! "
exit 1
fi
elif [ ${retval} -eq 0 ]; then
echo_g "Check network connectivity passed! "
echo
fi
}
function check_name_resolve(){
echo_b "checking DNS name resolve ... "
target_name_to_resolve="github.com"
stable_target_name_to_resolve="www.aliyun.com"
ping_count=1
if ! ping -c${ping_count} ${target_name_to_resolve} >/dev/null; then
echo_y "Name lookup failed for $target_name_to_resolve with $ping_count times "
if ping -c${ping_count} ${stable_target_name_to_resolve} >/dev/null; then
echo_g "Name lookup success for $stable_target_name_to_resolve with $ping_count times "
fi
eval_md5sum_of_nameserver_config="`md5sum /etc/resolv.conf | awk '{ print $1 }'`"
if test ${eval_md5sum_of_nameserver_config} = "674ea91675cdfac353bffbf49dc593c3"; then
echo_y "Nameserver config file is validated, but name lookup failed for $target_name_to_resolve with $ping_count times"
return 0
fi
[ -f /etc/resolv.conf ] && cp /etc/resolv.conf /etc/resolv.conf_$(date +%Y%m%d%H%M%S)~
cat >/etc/resolv.conf<<eof
nameserver 114.114.114.114
nameserver 8.8.4.4
eof
check_name_resolve
else
echo_g "Check DNS name resolve passed! "
echo
return 0
fi
}
command_exists() {
# which "$@" >/dev/null 2>&1
command -v "$@" >/dev/null 2>&1
}
check_command_can_be_execute(){
command_exists
}
yum_install_packages(){
echo_b "yum install $@ ..."
yum -q -yy install $@
retval=$?
if [ ${retval} -ne 0 ] ; then
echo_r "yum install $@ failed! "
exit 1
else
echo_g "yum install $@ successfully! "
fi
}
apt_get_install_packages(){
echo_b "apt-get install $@ ..."
apt-get -qq -y install $@
retval=$?
if [ ${retval} -ne 0 ] ; then
echo_r "apt-get install $@ failed! "
exit 1
else
echo_g "apt-get install $@ successfully! "
fi
}
# Refer: https://get.docker.com/
# 'curl -sSL https://get.docker.com/ | sh'
# or:
# 'wget -qO- https://get.docker.com/ | sh'
#
# Check if this is a forked Linux distro
check_linux_distribution_forked() {
# Check for lsb_release command existence, it usually exists in forked distros
if command_exists lsb_release; then
# Check if the `-u` option is supported
set +e
lsb_release -a -u > /dev/null 2>&1
lsb_release_exit_code=$?
set -e
# Check if the command has exited successfully, it means we're in a forked distro
if [ "$lsb_release_exit_code" = "0" ]; then
# Print info about current distro
# Get the upstream release info
lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[[:space:]]')
dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[[:space:]]')
cat <<-EOF
You're using '${lsb_dist}' version '${dist_version}'.
EOF
# Print info about upstream distro
cat <<-EOF
Upstream release is '${lsb_dist}' version '${dist_version}'.
EOF
else
if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ]; then
# We're Debian and don't even know it!
lsb_dist=debian
dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')"
case "$dist_version" in
8|'Kali Linux 2')
dist_version="jessie"
;;
7)
dist_version="wheezy"
;;
esac
fi
fi
fi
}
check_linux_distribution(){
# refer to /etc/issue and /etc/*-release maybe more better choice
# perform some very rudimentary platform detection
lsb_dist=''
dist_version=''
if command_exists lsb_release; then
lsb_dist="$(lsb_release -si)"
fi
DISTRIB_ID=""
if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then
lsb_dist="$(test -f /etc/lsb-release && . /etc/lsb-release && echo "$DISTRIB_ID")"
fi
if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then
lsb_dist='debian'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then
lsb_dist='fedora'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/oracle-release ]; then
lsb_dist='oracleserver'
fi
if [ -z "$lsb_dist" ]; then
if [ -r /etc/centos-release ] || [ -r /etc/redhat-release ]; then
lsb_dist='centos'
fi
fi
ID=""
if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
case "$lsb_dist" in
ubuntu)
if command_exists lsb_release; then
dist_version="$(lsb_release --codename | cut -f2)"
fi
DISTRIB_CODENAME=""
if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
fi
;;
debian)
dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')"
case "$dist_version" in
8)
dist_version="jessie"
;;
7)
dist_version="wheezy"
;;
esac
;;
oracleserver)
# need to switch lsb_dist to match yum repo URL
lsb_dist="oraclelinux"
dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')"
;;
fedora|centos)
dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')"
;;
*)
if command_exists lsb_release; then
dist_version="$(lsb_release --codename | cut -f2)"
fi
VERSION_ID=""
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
;;
esac
# Check if this is a forked Linux distro
check_linux_distribution_forked
}
# end Refer above
# refer to LNMP, http://lnmp.org/download.html
function Get_OS_Bit(){
if [[ `getconf WORD_BIT` = '32' && `getconf LONG_BIT` = '64' ]] ; then
Is_64bit='y'
else
Is_64bit='n'
fi
}
function Get_Dist_Name(){
if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
DISTRO='CentOS'
PM='yum'
elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then
DISTRO='RHEL'
PM='yum'
elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then
DISTRO='Aliyun'
PM='yum'
elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
DISTRO='Fedora'
PM='yum'
elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
DISTRO='Debian'
PM='apt'
elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
DISTRO='Ubuntu'
PM='apt'
elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then
DISTRO='Raspbian'
PM='apt'
else
DISTRO='unknow'
fi
Get_OS_Bit
}
function Get_RHEL_Version(){
Get_Dist_Name
if [ "${DISTRO}" = "RHEL" ]; then
if grep -Eqi "release 5." /etc/redhat-release; then
echo "Current Version: RHEL Ver 5"
RHEL_Ver='5'
elif grep -Eqi "release 6." /etc/redhat-release; then
echo "Current Version: RHEL Ver 6"
RHEL_Ver='6'
elif grep -Eqi "release 7." /etc/redhat-release; then
echo "Current Version: RHEL Ver 7"
RHEL_Ver='7'
fi
fi
}
function Get_ARM(){
if uname -m | grep -Eqi "arm"; then
Is_ARM='y'
fi
}
Install_LSB()
{
if [ "$PM" = "yum" ]; then
yum -y install redhat-lsb
elif [ "$PM" = "apt" ]; then
apt-get update
apt-get install -y lsb-release
fi
}
Get_Dist_Version()
{
Install_LSB
eval ${DISTRO}_Version=`lsb_release -rs`
eval echo "${DISTRO} \${${DISTRO}_Version}"
}
# end refer to http://lnmp.org/download.html
function restorecon_if_selinux_is_enabled(){
[ -f /selinux/enforce ] && SELINUX_STATE=$(cat "/selinux/enforce")
[ -n "$SELINUX_STATE" -a -x /sbin/restorecon ] && /sbin/restorecon -r $@
}
function backup_old_hosts_file(){
echo_b "backup old hosts file ... "
ops_time="$(date +%Y%m%d%H%M%S)~"
[ -f /etc/hosts ] && cp /etc/hosts /etc/hosts_${ops_time}
[ -f /etc/hosts_${ops_time} ] && echo_g "backup old hosts file successfully! file is\"/etc/hosts_$ops_time\" "
}
function roll_back_to_old_hosts_file(){
echo_b "rolling back to old hosts file ... "
if [ "x$ops_time" = "x" ]; then
echo_y "Can NOT find backup files, try to find a oldest backup manually! \
But do NOT worry, it usually because you have backup it last time"
oldest_backup_file="`find /etc -name hosts*~ ! -type d -printf "%T@ %p\n" | sort -n | head -n1 | awk '{print $NF}'`"
[ -f oldest_backup_file ] && \mv -f ${oldest_backup_file} /etc/hosts
[ -s /etc/hosts ] && echo_g "Rolling back to old hosts file successfully! "
else
\mv -f /etc/hosts_${ops_time} /etc/hosts
restorecon_if_selinux_is_enabled /etc/hosts
[ -s /etc/hosts ] && echo_g "Rolling back to old hosts file successfully! "
fi
}
function get_hosts_file_from_backup_site(){
echo_b "getting hosts file backup site ... "
if ! grep github /etc/hosts >/dev/null; then
backup_old_hosts_file
else
# TODO(Guodong Ding)
# rm: cannot remove ‘/etc/hosts’: Device or resource busy
# it occurs in docker when mount /etc/hosts to container as a volume
rm -f /etc/hosts
fi
wget -q https://coding.net/u/scaffrey/p/hosts/git/raw/master/hosts -O /etc/hosts
# test 1 -eq 2 # debug
if test $? -eq 0 -a -f /etc/hosts; then
echo_g "Get and set hosts file from backup site successfully! "
else
echo_r "Get hosts file from backup site failed! try to rolling back "
roll_back_to_old_hosts_file
fi
}
# AI: wget https://raw.githubusercontent.com/racaljk/hosts/master/hosts -qO /tmp/hosts && sudo sh -c 'cat /tmp/hosts > /etc/hosts'
function get_hosts_file_from_github(){
echo_b "getting hosts file from GitHub ... "
if [ ! -d hosts ]; then
command_exists git && git clone https://github.com/racaljk/hosts.git >/dev/null 2>&1
retval=$?
if [ ${retval} -ne 0 ] ; then
echo_r "git clone failed! "
get_hosts_file_from_backup_site
return
else
[ -s hosts/hosts ] && echo_g "git clone successfully! " || exit 1
fi
elif [ -d hosts/.git ]; then
echo_y "Note: a existed git repo is found! Attempt to update it! "
cd hosts
command_exists git && git pull >/dev/null 2>&1
# test 1 -eq 2 # debug
retval=$?
if [ ${retval} -ne 0 ] ; then
echo_r "git pull failed! "
get_hosts_file_from_backup_site
return
else
echo_g "git pull successfully! "
fi
cd ..
else
echo_r "There was a directory named \"hosts\", please remove it or change a work directory and try again, failed! "
exit 1
fi
if ! grep github /etc/hosts >/dev/null && test hosts/hosts -nt /etc/hosts; then
backup_old_hosts_file
[ -f hosts/hosts ] && \cp -f hosts/hosts /etc/hosts || ( echo_r "can NOT find file \"hosts/hosts\"" && exit 1 )
echo_g "Replace hosts file succeeded!"
else
# TODO(Guodong Ding)
# rm: cannot remove ‘/etc/hosts’: Device or resource busy
# it occurs in docker when mount /etc/hosts to container as a volume
rm -f /etc/hosts
[ -f hosts/hosts ] && \cp -f hosts/hosts /etc/hosts || ( echo_r "can NOT find file \"hosts/hosts\"" && exit 1 )
# check if able to resolve host `hostname -f`, if not, sudo will throw a exception 'sudo: unable to resolve host xxx'
echo "127.0.0.1 `hostname`" >> /etc/hosts
echo "127.0.0.1 `hostname -f`" >> /etc/hosts
echo "`ip addr show scope global $(ip route | awk '/^default/ {print $NF}') | awk -F '[ /]+' '/global/ {print $3}'` `hostname`" >> /etc/hosts
echo "`ip addr show scope global $(ip route | awk '/^default/ {print $NF}') | awk -F '[ /]+' '/global/ {print $3}'` `hostname -f`" >> /etc/hosts
echo_g "Replace hosts file succeeded!"
fi
}
function validate_network_to_outside(){
echo_b "validating hosts file ... "
for (( i=1 ; i<=3 ; i++ )) do
http_code=$(curl -o /dev/null -m 10 --connect-timeout 10 -s -w "%{http_code}" https://www.google.com.hk/)
retval=$?
if test "$http_code" = "200" -o ${http_code} -eq 200 ; then
echo_g "Now you can access Google via HTTPS not HTTP protocol, etc easily! "
break
else
echo "Process returned with HTTP code is: $http_code"
echo_y "replace hosts file failed! Try again, times $i"
fi
done
if [[ ${retval} -ne 0 ]]; then
echo "Process returned with exit RETURN code: $retval"
echo_r "Google can NOT be reached! Please let we know via email to \"[email protected]"\"
exit 1
fi
}
function validate_etc_host_conf(){
echo_b "validating /etc/host.conf file ... "
if [ -f /etc/host.conf ]; then
command_exists md5sum || ( echo_r "system is broken, md5sum comes from coreutils usually! " && exit 1 )
md5="`md5sum /etc/host.conf`"
content="`cat /etc/host.conf`"
if test "$md5" == "ea2ffefe1a1afb7042be04cd52f611a6" -o "$content" == "order hosts,bind" -o \
"$md5" == "4eb63731c9f5e30903ac4fc07a7fe3d6" -o "$content" == "multi on"; then
echo_g "Validating /etc/host.conf file passed! "
return
else
echo_y "Note: /etc/host.conf file's content is \"`cat /etc/host.conf`\""
return
fi
else
echo_y "System maybe broken, can NOT find file \"/etc/host.conf\", make a new one"
cat >/etc/host.conf<<eof
order hosts,bind
eof
fi
validate_etc_host_conf
}
# main function
# Run setup for each distro accordingly, install git here.
cat -<<eof
${header}
eof
check_network_connectivity
validate_etc_host_conf
check_name_resolve
check_linux_distribution
case "$lsb_dist" in
amzn)
;;
'opensuse project'|opensuse)
;;
'suse linux'|sle[sd])
;;
ubuntu)
command_exists git || apt_get_install_packages git
;;
centos)
command_exists git || yum_install_packages git
;;
*)
echo_r "unsupported system type"
exit 1
esac
get_hosts_file_from_github
validate_network_to_outside