-
Notifications
You must be signed in to change notification settings - Fork 0
/
block_app.html
427 lines (416 loc) · 16.9 KB
/
block_app.html
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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!-- 2023-01-06 Fri 19:33 -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>屏蔽钉钉微信等APP的几种思路</title>
<meta name="author" content="jamesarch" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<link rel="stylesheet" type="text/css" href="https://gongzhitaao.org/orgcss/org.css"/>
</head>
<body>
<div id="org-div-home-and-up">
<a accesskey="h" href="index.html"> UP </a>
|
<a accesskey="H" href="index.html"> HOME </a>
</div><div id="content" class="content">
<header>
<h1 class="title">屏蔽钉钉微信等APP的几种思路</h1>
</header><nav id="table-of-contents" role="doc-toc">
<h2>目录</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org60f963a">背景</a></li>
<li><a href="#orga5251c1">方法</a>
<ul>
<li><a href="#org5ffc5e4">屏蔽IP/域名</a>
<ul>
<li><a href="#org6c584ec">dnsmasq</a></li>
<li><a href="#org2dd1ab1">iptables</a></li>
<li><a href="#orgd5c8756">路由黑洞</a></li>
<li><a href="#org348f982">总结</a></li>
</ul>
</li>
<li><a href="#orgcbeb8b9">精准匹配</a>
<ul>
<li><a href="#org56d6b54">iptables</a>
<ul>
<li><a href="#org52bee10">string 模块</a></li>
<li><a href="#org12b2656">bpf 模块</a></li>
</ul>
</li>
<li><a href="#orgc01b8ff">xdp</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#orgbfeb52f">总结</a></li>
</ul>
</div>
</nav>
<div id="outline-container-org60f963a" class="outline-2">
<h2 id="org60f963a">背景</h2>
<div class="outline-text-2" id="text-org60f963a">
<p>
最近因业务需求要屏蔽指定APP的登录,在这中间走了不少弯路,在此记录下。
首先说下这里用到的抓包工具是<a href="https://wireshark.org">wireshark</a>和<a href="https://mirmproxy.org">mitmproxy</a>。网络环境是 <b>以Linux为出口或者网关的环境</b> 。屏蔽的思路,总结了下无非就是IP地址,域名,特定字符串这几种,接下来每个单独介绍下,以及所用到的工具。
</p>
</div>
</div>
<div id="outline-container-orga5251c1" class="outline-2">
<h2 id="orga5251c1">方法</h2>
<div class="outline-text-2" id="text-orga5251c1">
</div>
<div id="outline-container-org5ffc5e4" class="outline-3">
<h3 id="org5ffc5e4">屏蔽IP/域名</h3>
<div class="outline-text-3" id="text-org5ffc5e4">
</div>
<div id="outline-container-org6c584ec" class="outline-4">
<h4 id="org6c584ec">dnsmasq</h4>
<div class="outline-text-4" id="text-org6c584ec">
<p>
使用dnsmasq里面的重定向域名功能,将域名指定到一个不存在的地址,或者错误的地址,可以让解析失效,比如钉钉,可以在dnsmasq.conf里添加这两行,强制其解析到127.0.0.1。
</p>
<pre class="example">
address=/dingtalk.com/127.0.0.1
address=/dingtalkapp.com/127.0.0.1
</pre>
</div>
</div>
<div id="outline-container-org2dd1ab1" class="outline-4">
<h4 id="org2dd1ab1">iptables</h4>
<div class="outline-text-4" id="text-org2dd1ab1">
<p>
iptables这个方法就比较复杂了,首先要抓到域名解析对应的IP地址,然后将其整理汇总。
以钉钉的login.dingtalk.com的解析地址为例 我本地解析到的IP地址是106.11.40.32,通过<a href="https://bgp.he.net">bgp.he.net</a>查询到其网段所属的ASN有两个:
106.11.40.0/21和106.11.0.0/16,取其中较小的网段106.11.40.0/21来进行屏蔽,避免误屏蔽。
</p>
<div class="org-src-container">
<pre class="src src-shell">iptables -A INPUT -s 106.11.40.0/21 -j DROP
iptables -A OUTPUT -s 106.11.40.0/21 -j DROP
</pre>
</div>
</div>
</div>
<div id="outline-container-orgd5c8756" class="outline-4">
<h4 id="orgd5c8756">路由黑洞</h4>
<div class="outline-text-4" id="text-orgd5c8756">
<p>
路由黑洞和上述iptables原理一致,都是屏蔽指定的IP段,代码如下
</p>
<div class="org-src-container">
<pre class="src src-shell">ip route add blackhole 106.11.40.0/21
</pre>
</div>
</div>
</div>
<div id="outline-container-org348f982" class="outline-4">
<h4 id="org348f982">总结</h4>
<div class="outline-text-4" id="text-org348f982">
<p>
以上方法只能说是简单粗暴,像QQ微信钉钉这种大厂出品的会有对应的反屏蔽策略,比如QQ:
假如发现你屏蔽DNS解析,那我就直连IP,不走本地解析。
IP屏蔽这个就更原始了,各个大厂的IP段数不胜数,而且误封的可能性极大。所以以上这几种方法只适用于:
登录IP/域名固定的,解析单台服务器的APP或者网站这些场景。
</p>
</div>
</div>
</div>
<div id="outline-container-orgcbeb8b9" class="outline-3">
<h3 id="orgcbeb8b9">精准匹配</h3>
<div class="outline-text-3" id="text-orgcbeb8b9">
</div>
<div id="outline-container-org56d6b54" class="outline-4">
<h4 id="org56d6b54">iptables</h4>
<div class="outline-text-4" id="text-org56d6b54">
<p>
这里说的精准匹配是指域名或者对应的数据包头,以QQ和钉钉为例,通过抓包知道钉钉的登录服务器为login.dingtalk.com,QQ发送给登录服务器的数据包有规律且前几位十六进制字符串为00 a5 02 3a 45 08 25,如下图所示
<img src="./asserts/img/qq_login.png" alt="qq_login.png">
</p>
</div>
<div id="outline-container-org52bee10" class="outline-5">
<h5 id="org52bee10">string 模块</h5>
<div class="outline-text-5" id="text-org52bee10">
<p>
iptables里的string模块有两种匹配方式,一种是常规的字符串,另一种就是十六进制字符串,使用方法分别如下
</p>
<div class="org-src-container">
<pre class="src src-shell"><span style="color: #5B6268;"># </span><span style="color: #5B6268;">屏蔽钉钉登录服务器</span>
iptables -A INPUT -m string --string <span style="color: #98be65;">"im.dingtalk.com"</span> --algo bm -j DROP
</pre>
</div>
<div class="org-src-container">
<pre class="src src-shell"><span style="color: #5B6268;"># </span><span style="color: #5B6268;">屏蔽QQ登录服务器</span>
iptables -A INPUT --match string --algo kmp --hex-string <span style="color: #98be65;">'|00 a5 02 3a 45 08 25|'</span> -j DROP
</pre>
</div>
<p>
以上两种都是屏蔽常规的字符串,下面这种屏蔽PC 微信的方法需要用到正则表达式模块,需要自己单独编译,推荐DKMS编译
<a href="https://github.com/smcho-kr/kpcre/wiki/Step-by-step-installation-guide">https://github.com/smcho-kr/kpcre/wiki/Step-by-step-installation-guide</a>
这个正则表达式的使用方法和平时我们使用的不大一样,参考以下文章
<a href="https://github.com/smcho-kr/kpcre/wiki">https://github.com/smcho-kr/kpcre/wiki</a>
</p>
<p>
在编译安装完成之后,可以运行以下命令来屏蔽微信登录。屏蔽原理是匹配MicroMessenger这个HTTP UA 如果匹配到就丢弃数据包
</p>
<div class="org-src-container">
<pre class="src src-shell">iptables -A INPUT -m string --string <span style="color: #98be65;">'/^MicroMessenger.*/'</span> --algo pcre -j DROP
</pre>
</div>
</div>
</div>
<div id="outline-container-org12b2656" class="outline-5">
<h5 id="org12b2656">bpf 模块</h5>
<div class="outline-text-5" id="text-org12b2656">
<p>
bpf模块这个比较新,需要在iptables 1.4.19以上版本 其中用到的nfbpf_compile这个命令在centos 7这个版本是没有的,可以使用tcpdump生成对应的cBPF字节码
</p>
<div class="org-src-container">
<pre class="src src-shell">ip tuntap add tun0 mode tun
ip link set tun0 up
tcpdump -ddd -i tun0 dst host im.dingtalk.com | sed <span style="color: #98be65;">':a;N;$!ba;s/\n/,/g'</span>
</pre>
</div>
<p>
对应的nfbpf_compile命令如下
</p>
<div class="org-src-container">
<pre class="src src-shell"> nfbpf_compile RAW <span style="color: #98be65;">'dst host im.dingtalk.com'</span>
</pre>
</div>
<p>
具体的文档可以参考这个 <a href="https://fossies.org/linux/iptables/extensions/libxt_bpf.man">https://fossies.org/linux/iptables/extensions/libxt_bpf.man</a>
</p>
<p>
还是以钉钉为例
</p>
<div class="org-src-container">
<pre class="src src-shell"><span style="color: #5B6268;">#</span><span style="color: #5B6268;">以下代码未验证</span>
iptables -A INPUT -m bpf --bytecode <span style="color: #98be65;">"</span><span style="color: #51afef; font-weight: bold;">`nfbpf_compile RAW 'dst host im.dingtalk.com'`</span><span style="color: #98be65;">"</span> -j DROP
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgc01b8ff" class="outline-4">
<h4 id="orgc01b8ff">xdp</h4>
<div class="outline-text-4" id="text-orgc01b8ff">
<p>
XDP(eXpress Data Path) 是Linux 4.8之后基于ePBF(extended BPF)推出的一个新特性,其特点是数据直接发送到网卡,可以实现高性能处理数据。
通过编写对应的C程序来实现对特定数据包的拦截或者放行,具体实现可以参考这个项目
</p>
<p>
<a href="https://github.com/xdp-project/xdp-tools/tree/master/xdp-filter">https://github.com/xdp-project/xdp-tools/tree/master/xdp-filter</a>
</p>
<p>
因涉及到底层的数据解析匹配,难度较大。但是性能这块会比iptables和上述几种方法快很多,具体数据对比可参考此链接
</p>
<p>
<a href="https://blog.cloudflare.com/how-to-drop-10-million-packets/">https://blog.cloudflare.com/how-to-drop-10-million-packets/</a>
</p>
</div>
</div>
</div>
</div>
<div id="outline-container-orgbfeb52f" class="outline-2">
<h2 id="orgbfeb52f">总结</h2>
<div class="outline-text-2" id="text-orgbfeb52f">
<p>
这篇文章只是对自己在工作过程中的一个思考整理,如有遗漏或者不正确的地方还请见谅。另外打一个小广告,我创建了一个Layer 7防火墙的项目,大概架构是特征库+XDP来实现高性能数据屏蔽处理。感兴趣的同学可以考虑加入下
</p>
<p>
<a href="https://github.com/k-breaker">https://github.com/k-breaker</a>
</p>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">作者: jamesarch</p>
<p class="date">Created: 2023-01-06 Fri 19:33</p>
</div>
</body>
</html>