-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
executable file
·476 lines (257 loc) · 105 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>为什么这么涛的个人博客</title>
<subtitle>做一件事最好的时机是十年前,其次就是现在</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://scoolor.github.io/"/>
<updated>2019-09-25T07:32:23.213Z</updated>
<id>https://scoolor.github.io/</id>
<author>
<name>为什么这么涛</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>PHP foreach 使用引用陷阱</title>
<link href="https://scoolor.github.io/2019/09/25/PHP-foreach-%E4%BD%BF%E7%94%A8%E5%BC%95%E7%94%A8%E9%99%B7%E9%98%B1/"/>
<id>https://scoolor.github.io/2019/09/25/PHP-foreach-使用引用陷阱/</id>
<published>2019-09-25T07:31:41.000Z</published>
<updated>2019-09-25T07:32:23.213Z</updated>
<content type="html"><![CDATA[<p>有时间我们在使用foreach时需要改变数组原有项的值,需要传入一个&,表示使用数组原有的值,而不是一个复制值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$arr = range(1,3);</span><br><span class="line">foreach($arr as $k => &$v) {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">var_dump($arr); //1 2 3</span><br><span class="line"></span><br><span class="line">foreach($arr as $v) {</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">var_dump($arr); // 1 2 2</span><br></pre></td></tr></table></figure><p>如上第二个循环输出的是1 2 2 ,而不是1 2 3<br>第一个循环以 <code>&$v</code> 传入引用,循环结束后$v指向$arr[2],第二个循环使用的 $v 仍然是引用,仍然指向$arr[2],这样第二个循环的第一次是$arr[0]即 1 赋值给$arr[2],<br>第二次是$arr[1]即 2 赋值给$arr[2],第三次是$arr[2]即2赋值给$arr[2],所以打印 1 2 2。</p><h2 id="如何避免这个问题?"><a href="#如何避免这个问题?" class="headerlink" title="如何避免这个问题?"></a>如何避免这个问题?</h2><p>1、在第二次循环之前,unset($value)<br>2、第二次foreach的时候使用不同名字的变量,如$item</p>]]></content>
<summary type="html">
<p>有时间我们在使用foreach时需要改变数组原有项的值,需要传入一个&amp;,表示使用数组原有的值,而不是一个复制值。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span
</summary>
</entry>
<entry>
<title>TOML 简介</title>
<link href="https://scoolor.github.io/2019/01/10/toml/"/>
<id>https://scoolor.github.io/2019/01/10/toml/</id>
<published>2019-01-10T10:10:40.000Z</published>
<updated>2019-01-10T10:26:14.190Z</updated>
<content type="html"><![CDATA[<p>TOML 的全称是 Tom’s Obvious, Minimal Language,因为它的作者是 GitHub 联合创始人 Tom Preston-Werner, TOML 这个名字贼逗。</p><p>TOML 是目录最优秀的配置文件格式方案,相较于yaml、json、ini,优势很明显。目前很多新项目直接使用 TOML作为配置文件的格式,比如golang官方的go.mod。</p><h2 id="TOML-的目标"><a href="#TOML-的目标" class="headerlink" title="TOML 的目标"></a>TOML 的目标</h2><p>TOML 的目标是成为一个极简的配置文件格式。TOML 被设计成可以无歧义地被映射为哈希表,从而被多种语言解析。</p><h2 id="官方示例"><a href="#官方示例" class="headerlink" title="官方示例"></a>官方示例</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">title = "TOML 例子"</span><br><span class="line"></span><br><span class="line">[owner]</span><br><span class="line">name = "Tom Preston-Werner"</span><br><span class="line">organization = "GitHub"</span><br><span class="line">bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."</span><br><span class="line">dob = 1979-05-27T07:32:00Z # 日期时间是一等公民。为什么不呢?</span><br><span class="line"></span><br><span class="line">[database]</span><br><span class="line">server = "192.168.1.1"</span><br><span class="line">ports = [ 8001, 8001, 8002 ]</span><br><span class="line">connection_max = 5000</span><br><span class="line">enabled = true</span><br><span class="line"></span><br><span class="line">[servers]</span><br><span class="line"></span><br><span class="line"> # 你可以依照你的意愿缩进。使用空格或Tab。TOML不会在意。</span><br><span class="line"> [servers.alpha]</span><br><span class="line"> ip = "10.0.0.1"</span><br><span class="line"> dc = "eqdc10"</span><br><span class="line"></span><br><span class="line"> [servers.beta]</span><br><span class="line"> ip = "10.0.0.2"</span><br><span class="line"> dc = "eqdc10"</span><br><span class="line"></span><br><span class="line">[clients]</span><br><span class="line">data = [ ["gamma", "delta"], [1, 2] ]</span><br><span class="line"></span><br><span class="line"># 在数组里换行没有关系。</span><br><span class="line">hosts = [</span><br><span class="line"> "alpha",</span><br><span class="line"> "omega"</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h2 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h2><p>使用 <code>#</code> 注释:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># I am a comment. Hear me roar. Roar.</span><br><span class="line">key = "value" # Yeah, you can do this.</span><br></pre></td></tr></table></figure><h2 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wrong = "C:\Users\nodejs\templates" # 注意:这不会生成合法的路径。</span><br><span class="line">right = "C:\\Users\\nodejs\\templates"</span><br></pre></td></tr></table></figure><h2 id="布尔值"><a href="#布尔值" class="headerlink" title="布尔值"></a>布尔值</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 布尔值永远是小写</span><br><span class="line">true</span><br><span class="line">false</span><br></pre></td></tr></table></figure><h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p>数组使用方括号包裹。空格会被忽略。元素使用逗号分隔。注意,不允许混用数据类型。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[ 1, 2, 3 ]</span><br><span class="line">[ "red", "yellow", "green" ]</span><br><span class="line">[ [ 1, 2 ], [3, 4, 5] ]</span><br><span class="line">[ [ 1, 2 ], ["a", "b", "c"] ] # 这是可以的。</span><br><span class="line">[ 1, 2.0 ] # 注意:这是不行的。</span><br></pre></td></tr></table></figure><p>以上基本覆盖了配置的使用场景,TOML 各个语言支持都很好,直接使用即可。</p>]]></content>
<summary type="html">
<p>TOML 的全称是 Tom’s Obvious, Minimal Language,因为它的作者是 GitHub 联合创始人 Tom Preston-Werner, TOML 这个名字贼逗。</p>
<p>TOML 是目录最优秀的配置文件格式方案,相较于yaml、json、
</summary>
<category term="TOML" scheme="https://scoolor.github.io/tags/TOML/"/>
</entry>
<entry>
<title>LMbench 安装与使用</title>
<link href="https://scoolor.github.io/2019/01/01/LMbench/"/>
<id>https://scoolor.github.io/2019/01/01/LMbench/</id>
<published>2019-01-01T02:40:09.000Z</published>
<updated>2019-01-01T12:12:56.180Z</updated>
<content type="html"><![CDATA[<p>LMbench 能深入操作系统的关键参数,帮助我们了解一些关键的指标参数,比如上下文切换所需的时间,对于了解操作系统指标,分析解决性能问题有很大帮助。</p><h2 id="LMbench-介绍"><a href="#LMbench-介绍" class="headerlink" title="LMbench 介绍"></a>LMbench 介绍</h2><p>Lmbench是一套简易,可移植的,符合ANSI/C标准为UNIX/POSIX而制定的微型测评工具。<br>一般来说,它衡量两个关键特征:反应时间和带宽。<br>Lmbench旨在使系统开发者深入了解关键操作的基础成本。</p><h2 id="安装LMbench"><a href="#安装LMbench" class="headerlink" title="安装LMbench"></a>安装LMbench</h2><ol><li>下载 LMbench, <a href="http://www.bitmover.com/lmbench" target="_blank" rel="noopener">http://www.bitmover.com/lmbench</a></li><li>安装</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># cd lmbench3</span><br><span class="line"># make</span><br></pre></td></tr></table></figure><p>如果遇到如下错误,请执行:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">gmake[2]: *** No rule to make target `../SCCS/s.ChangeSet', needed by `bk.ver'. Stop.</span><br><span class="line">gmake[2]: Leaving directory `/root/lmbench3/src'</span><br><span class="line">make[1]: *** [lmbench] Error 2</span><br><span class="line">make[1]: Leaving directory `/root/lmbench3/src'</span><br><span class="line">make: *** [build] Error 2</span><br><span class="line">Just ignore the errors, and there is also a method to avoid the errors:</span><br><span class="line"># mkdir SCCS</span><br><span class="line"># touch SCCS/s.ChangeSet</span><br></pre></td></tr></table></figure><h2 id="主要功能介绍"><a href="#主要功能介绍" class="headerlink" title="主要功能介绍"></a>主要功能介绍</h2><p>LMbench的主要功能:</p><p><strong>带宽测评工具</strong></p><ul><li>读取缓存文件</li><li>拷贝内存</li><li>读内存</li><li>写内存</li><li>管道</li><li>TCP</li></ul><p><strong>反应时间测评工具</strong></p><ul><li>上下文切换</li><li>网络: 连接的建立,管道,TCP,UDP和RPC hot potato</li><li>文件系统的建立和删除</li><li>进程创建</li><li>信号处理</li><li>上层的系统调用</li><li>内存读入反应时间</li></ul><p><strong>其他</strong></p><ul><li>处理器时钟比率计算</li></ul><h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><p>运行<code>make results</code>,会让你做一些配置上的选择,然后会生成一个对应的配置,执行时间较慢,需要等待大约半个小时,运行结束后,执行 <code>make see</code> 查看测试报告。</p>]]></content>
<summary type="html">
<p>LMbench 能深入操作系统的关键参数,帮助我们了解一些关键的指标参数,比如上下文切换所需的时间,对于了解操作系统指标,分析解决性能问题有很大帮助。</p>
<h2 id="LMbench-介绍"><a href="#LMbench-介绍" class="headerli
</summary>
</entry>
<entry>
<title>聊聊Cookie那些事</title>
<link href="https://scoolor.github.io/2018/11/13/cookie/"/>
<id>https://scoolor.github.io/2018/11/13/cookie/</id>
<published>2018-11-13T15:06:28.000Z</published>
<updated>2018-11-14T03:10:11.720Z</updated>
<content type="html"><![CDATA[<h2 id="为什么使用cookies"><a href="#为什么使用cookies" class="headerlink" title="为什么使用cookies?"></a>为什么使用cookies?</h2><p>因为HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分是不是来源于同一个浏览器。所以,需要额外的数据用于维护会话。 Cookie 正是这样的一段随HTTP请求一起被传递的额外数据。</p><h2 id="Cookie的工作原理"><a href="#Cookie的工作原理" class="headerlink" title="Cookie的工作原理"></a>Cookie的工作原理</h2><p>Cookie 是浏览器提供的功能,用于存储服务器的一段文本信息,每个 Cookie 的大小一般不能超过4KB。浏览器每次向服务器发出 HTTP 请求,浏览器就会检查是否有域名相应的Cookie,如果有就会在 request header 中添加 Cookie 信息。</p><p>Cookie 本质上是浏览器存储数据的方式,只不过,这部分数据会自动携带到 Http 的请求头中。</p><h2 id="创建-Cookie"><a href="#创建-Cookie" class="headerlink" title="创建 Cookie"></a>创建 Cookie</h2><p>Web 服务器通过发送一个称为 Set-Cookie 的 HTTP 消息头来创建一个 cookie,Set-Cookie 消息头是一个字符串,其格式如下(中括号中的部分是可选的):</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]</span><br></pre></td></tr></table></figure><h2 id="Cookie的属性"><a href="#Cookie的属性" class="headerlink" title="Cookie的属性"></a>Cookie的属性</h2><p>每个cookie都有一定的属性,如什么时候失效,要发送到哪个域名,哪个路径等等。这些属性是通过cookie选项来设置的,cookie选项包括:expires、domain、path、secure、HttpOnly。在设置任一个cookie时都可以设置相关的这些属性,当然也可以不设置,这时会使用这些属性的默认值。在设置这些属性时,属性之间由一个分号和一个空格隔开。</p><p>代码示例如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"key=name; expires=Thu, 25 Feb 2016 04:18:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"</span><br></pre></td></tr></table></figure><h3 id="domain-选项"><a href="#domain-选项" class="headerlink" title="domain 选项"></a>domain 选项</h3><p>指定了 cookie 将要被发送至哪个或哪些域中。默认情况下,domain 会被设置为创建该 cookie 的页面所在的域名,所以当给相同域名发送请求时该 cookie 会被发送至服务器。</p><p>主域下的 Cookie 会扩散到该主域下所有的子域上。例如:a.com有cookie,用户访问b.a.com时,也会获取到a.com下的cookie。</p><h3 id="path-选项"><a href="#path-选项" class="headerlink" title="path 选项"></a>path 选项</h3><p>path 选项指定了请求的资源 URL 中必须存在指定的路径时,才会发送Cookie 消息头。这个比较通常是将 path 选项的值与请求的 URL 从头开始逐字符比较完成的。如果字符匹配,则发送 Cookie 消息头,例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Set-Cookie:name=Scoolor; path=/blog</span><br></pre></td></tr></table></figure><h3 id="secure-选项"><a href="#secure-选项" class="headerlink" title="secure 选项"></a>secure 选项</h3><p>secure选项,不像其它选项,该选项只是一个标记而没有值。只有当一个请求通过 SSL 或 HTTPS 创建时,包含 secure 选项的 cookie 才能被发送至服务器。这种 cookie 的内容具有很高的价值,如果以纯文本形式传递很有可能被篡改,例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Set-Cookie: name=Scoolor; secure</span><br></pre></td></tr></table></figure><h3 id="HTTP-only"><a href="#HTTP-only" class="headerlink" title="HTTP-only"></a>HTTP-only</h3><p>HTTP-Only 是告诉浏览器 cookie 不能通过 JavaScript 的 document.cookie 属性访问。设计该特征意在提供一个安全措施来帮助阻止通过 JavaScript 发起的跨站脚本攻击 (XSS) 窃取 cookie 的行为。</p><h2 id="设置cookie的方式"><a href="#设置cookie的方式" class="headerlink" title="设置cookie的方式"></a>设置cookie的方式</h2><ol><li>http response Set-Cookie</li></ol><p>使用http Response Headers 可以通过浏览器自动设置cookie</p><ol start="2"><li>JavaScript set cookie</li></ol><p>JavaScript也可以设置Cookie,本质与浏览器通过 Http response 获取cookie自动设置一致,只是JavaScript 帮浏览器进行了设置。在 JavaScript 中通过 document.cookie 属性,你可以创建、维护和删除 cookie。</p><h2 id="Cookie的限制"><a href="#Cookie的限制" class="headerlink" title="Cookie的限制"></a>Cookie的限制</h2><ol><li>单个域名的所有cookie的大小不能超过4KB,最后设置的cookie如果超过4KB限制,设置会失败。</li><li>单个域名cookie数量最多50个,safari和chrome没有数量限制。</li><li>cookie数量越多,体积越大,便会影响服务器传输效率,所以要慎用cookie,只把必须要带给服务器的数据设置到cookie中。</li></ol><h2 id="跨域传输-Cookie"><a href="#跨域传输-Cookie" class="headerlink" title="跨域传输 Cookie"></a>跨域传输 Cookie</h2><p>现在很多应用都做了前后端的分离,会涉及到跨域传输Cookie的问题,当然不一定要使用HTTP request的方式发送cookie,可以直接放到URL中传输,哈哈哈。默认情况下,Cookie 不能跨域传输,如果要跨域传输,需要服务端同意,同时客户端需要开启<code>withCredentials</code>属性,具体如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">浏览器设置:</span><br><span class="line">xhr.withCredentials=true</span><br><span class="line"></span><br><span class="line">服务端设置响应头:</span><br><span class="line">Access-Control-Allow-Credentials:true</span><br><span class="line">Access-Control-Allow-Origin: http://www.xxx.com(注意这里设为*不行,没做测试)</span><br></pre></td></tr></table></figure><h2 id="Cookie的设置与读取"><a href="#Cookie的设置与读取" class="headerlink" title="Cookie的设置与读取"></a>Cookie的设置与读取</h2><p>测试了若干种设置与读取的方式,可能不全,应该能涵盖到大多数情况。</p><ol><li>相同域名,不可以跨路径设置与读取 Cookie</li><li>子域可以读取对应主域下的 Cookie,如a.b.com,可以读取b.com域下的cookie</li><li>子域可以设置对应主域下的 Cookie,如a.b.com,可以设置b.com域下的cookie</li><li>Cookie 不可以跨域名设置与读取,即便是相同主域不同子域也不可以相互读取设置,如a.b.com不能设置b.b.com的cookie</li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Cookie 存在时间已经很久远了,各个浏览器之前的处理方式也各有不同,这不是一篇系统性讲解的文章,这里不做太多介绍,只涉及一些比较通用的部分,希望帮助大家理解 Cookie。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="https://www.cnblogs.com/yinian/p/8371746.html" target="_blank" rel="noopener">https://www.cnblogs.com/yinian/p/8371746.html</a></li><li><a href="https://segmentfault.com/a/1190000004556040" target="_blank" rel="noopener">https://segmentfault.com/a/1190000004556040</a></li><li><a href="https://www.jianshu.com/p/090b971c048b" target="_blank" rel="noopener">https://www.jianshu.com/p/090b971c048b</a></li></ol>]]></content>
<summary type="html">
<h2 id="为什么使用cookies"><a href="#为什么使用cookies" class="headerlink" title="为什么使用cookies?"></a>为什么使用cookies?</h2><p>因为HTTP协议是无状态的,对于一个浏览器发出的多次请求
</summary>
<category term="cookie" scheme="https://scoolor.github.io/tags/cookie/"/>
</entry>
<entry>
<title>分析网页在请求过程中,浏览器中断请求这期间发生的事</title>
<link href="https://scoolor.github.io/2018/11/11/browser-interrupt/"/>
<id>https://scoolor.github.io/2018/11/11/browser-interrupt/</id>
<published>2018-11-11T12:54:59.000Z</published>
<updated>2018-11-13T10:20:42.290Z</updated>
<content type="html"><![CDATA[<p>事情是这样,公司一个项目,使用浏览器访问时快速刷新页面会遇到问题,页面其中一个ajax请求过程比较长,快速刷新时该请求没有完成,请求会中断,nginx也没有收到该请求的日志,而且chrome(windows和mac)和firefox(windows)下的现象不一致,而在mac平台下firefox却没有问题,实践操作,分析一下这其中发生的事情。</p><p>首先模拟类似的场景,在本地虚拟机中创建 lnmp 环境,请求过程中直接 sleep 20 秒,使用 wireshark 抓包分析,查看 nginx 日志。</p><p>chrome和firefox默认情况下的请求头都带有<code>Connection:keep-alive</code>的标识,服务端也可以进行<code>Connection</code>的配置,表示了服务端接受或者拒绝<code>keep-alive</code>。</p><h2 id="条件1"><a href="#条件1" class="headerlink" title="条件1"></a>条件1</h2><p>在 mac 环境下使用 chrome 访问页面,服务端配置 持久性连接,即 connection:keep-alive。</p><h3 id="在不中断请求的情况下"><a href="#在不中断请求的情况下" class="headerlink" title="在不中断请求的情况下"></a>在不中断请求的情况下</h3><p>先进行TCP的三次握手,建立TCP连接(在0.001s内完成),客户端等待服务端响应,在前20s内nginx没有日志记录,在20s时完成http的response,nginx同时记录请求日志,状态码为200。</p><p>约86s时客户端发起了 TCP Keep-Alive,在196秒时,服务端发起了RST,tcp连接断开。</p><p>Nginx默认的Http keep-alive timeout是65s;</p><p>下图为wireshark的封包记录:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541946498/WX20181111-222740_2x.png" alt="wireshark封包记录"></p><h3 id="在中断请求的情况下"><a href="#在中断请求的情况下" class="headerlink" title="在中断请求的情况下"></a>在中断请求的情况下</h3><p>同样先进行TCP的三次握手,建立TCP连接,这时刷新浏览器,nginx记录了日志,日志状态码为499,浏览器的网络状态是<code>canceled</code>,此时TCP连接依然是 <code>ESTABLISHED</code> 状态;中断请求时,服务端收到客户端的FIN包,但是连接依然是连接状态。在150s时服务端发起了RST,TCP连接断开。服务端收到FIN请求,自然不会再做出http响应,详见Wireshark封包记录。</p><p>在刷新浏览器后,连接依然会保持,由浏览器维持了这个连接,连接依然是可重用的,不需要重新建立。</p><p>Nginx 499 对应的是 “client has closed connection”,表示服务器返回http响应之前,客户端就提前关闭了http连接。</p><p>下图为wireshark的封包记录:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541946167/WX20181111-222210_2x.png" alt="wireshark封包记录"></p><h2 id="条件2"><a href="#条件2" class="headerlink" title="条件2"></a>条件2</h2><p>在 mac 环境下使用 chrome 访问页面,服务端配置 非持久性连接,即 connection:close。</p><p>在非持久连接情况下,客户端不再发起 TCP Keep-Alive心跳包,而是正常经由发送FIN包由服务端time_wait=》close断开TCP连接。在中断请求的情况下,再刷新就是建立新的TCP连接了。</p><p>在中断请求的情况下,nginx记录一条状态码为499的日志记录。</p><p>下图为wireshark的封包记录:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541951553/WX20181111-235214_2x.png" alt="wireshark封包记录"></p><h2 id="条件3"><a href="#条件3" class="headerlink" title="条件3"></a>条件3</h2><p>在mac环境下,使用Firefox访问页面,服务端配置 非持久连接。</p><h3 id="在不中断请求的情况下-1"><a href="#在不中断请求的情况下-1" class="headerlink" title="在不中断请求的情况下"></a>在不中断请求的情况下</h3><p>Wireshark显示即便在非持久连接的情况下,客户端发起了Keep-Alive心跳包(这是由于服务端sleep20s导致,客户端发起了心跳检测),每隔10s中发起一次Keep-Alive包。其他并无太大区别。</p><p>具体情况详见Wireshark抓包详图:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541952720/WX20181112-001055_2x.png" alt="wireshark封包记录"></p><h3 id="在中断请求的情况下-1"><a href="#在中断请求的情况下-1" class="headerlink" title="在中断请求的情况下"></a>在中断请求的情况下</h3><p>没有出现<code>FIN_WAIT2</code>状态,直接由客户端关闭了TCP连接。</p><p>具体情况详见Wireshark抓包详图:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541953119/WX20181112-001824_2x.png" alt="wireshark封包记录"></p><h2 id="条件4"><a href="#条件4" class="headerlink" title="条件4"></a>条件4</h2><p>mac环境下,使用Firefox访问页面,服务端配置 持久连接。</p><p>服务端没有发送RST包,而是由客户端发起的FIN包断开了TCP连接,其他并无太大不同;同样Keep-Alive还是每隔10s一次;具体见下图。</p><h3 id="不中断情况下"><a href="#不中断情况下" class="headerlink" title="不中断情况下"></a>不中断情况下</h3><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541953976/WX20181112-003230_2x.png" alt="wireshark封包记录"></p><h3 id="中断情况下"><a href="#中断情况下" class="headerlink" title="中断情况下"></a>中断情况下</h3><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541954106/WX20181112-003451_2x.png" alt="wireshark封包记录"></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>由于没有windows环境,就暂不进行分析了。由以上分析可见firefox和chrome在处理网络请求的一些细节上还是有很大的不同。</p>]]></content>
<summary type="html">
<p>事情是这样,公司一个项目,使用浏览器访问时快速刷新页面会遇到问题,页面其中一个ajax请求过程比较长,快速刷新时该请求没有完成,请求会中断,nginx也没有收到该请求的日志,而且chrome(windows和mac)和firefox(windows)下的现象不一致,而在ma
</summary>
<category term="TCP" scheme="https://scoolor.github.io/tags/TCP/"/>
<category term="HTTP" scheme="https://scoolor.github.io/tags/HTTP/"/>
</entry>
<entry>
<title>网络协议简介</title>
<link href="https://scoolor.github.io/2018/11/11/internet-protocol/"/>
<id>https://scoolor.github.io/2018/11/11/internet-protocol/</id>
<published>2018-11-11T01:54:37.000Z</published>
<updated>2018-11-11T06:52:57.170Z</updated>
<content type="html"><![CDATA[<p>互联网协议分为好几层,每一层都有自己的功能定位,一般分为5层比较容易理解。</p><h2 id="应用层(Application-Layer)"><a href="#应用层(Application-Layer)" class="headerlink" title="应用层(Application Layer)"></a>应用层(Application Layer)</h2><p>应用层直接面向用户,规定了应用程序的数据格式,数据格式放入UDP或TCP的Data中,文件传输,电子邮件,文件服务,虚拟终端。常见协议:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet; </p><h2 id="传输层(Transport-Layer)"><a href="#传输层(Transport-Layer)" class="headerlink" title="传输层(Transport Layer)"></a>传输层(Transport Layer)</h2><p>提供端对端的接口;有了mac地址和IP协议,两台机器就可以建立连接了,但是每台主机上有很多不同的应用程序,需要建立端口到端口的通信,Unix系统把“主机+端口”称为Socket,基于Socket,可以产生TCP和UDP协议。对应协议:TCP,UDP;</p><p>“端口”是0到65535之间的一个整数,正好16个二进制位。0到1023的端口被系统占用,用户只能选用大于1023的端口。不管是浏览网页还是在线聊天,应用程序会随机选用一个端口,然后与服务器的相应端口联系。</p><h2 id="网络层(Network-Layer)"><a href="#网络层(Network-Layer)" class="headerlink" title="网络层(Network Layer)"></a>网络层(Network Layer)</h2><p>为数据包选择路由,由于数据链路层的以太网协议依靠mac地址在网络上以广播的形式发送数据包,但是总不能在全世界范围内广播吧,网络层的主要任务就是为了<em>选择合适的路由和交换节点</em>,使传输层传下来的分组信息能够准确无误的找到目的地址,并交付给相应的传输层。即完成网络寻址功能。对应协议:IP,ICMP,RIP,OSPF,BGP,IGMP;</p><h3 id="IP协议"><a href="#IP协议" class="headerlink" title="IP协议"></a>IP协议</h3><p>IP协议的两个主要作用,为每台计算机分配IP地址;确定哪些地址在同一个子网;IP协议在以太网的数据内部,如果IP数据包超过1500个字节需要分开发送;</p><h3 id="ICMP"><a href="#ICMP" class="headerlink" title="ICMP"></a>ICMP</h3><p>主要功能包括,确认 IP 包是否成功送达目标地址,通知在发送过程当中 IP 包被废弃的具体原因,改善网络设置等。<br>IPv4 中 ICMP 仅作为一个辅助作用支持 IPv4。也就是说,在 IPv4 时期,即使没有 ICMP,仍然可以实现 IP 通信。然而,在 IPv6 中,ICMP 的作用被扩大,如果没有 ICMPv6,IPv6 就无法进行正常通信;</p><h3 id="IP数据包"><a href="#IP数据包" class="headerlink" title="IP数据包"></a>IP数据包</h3><p>根据IP协议发送的数据,就叫做IP数据包,其中必定包括IP地址信息;</p><h3 id="ARP协议"><a href="#ARP协议" class="headerlink" title="ARP协议"></a>ARP协议</h3><p>用来在子网内从IP地址得到MAC地址,不在同一个子网需要交给网关处理;</p><h3 id="NAT"><a href="#NAT" class="headerlink" title="NAT"></a>NAT</h3><p>NAT(Network Address Translator)是用于在本地网络中使用私有地址,在连接互联网时转而使用全局 IP 地址的技术;</p><ol><li>源NAT(Source NAT,SNAT):修改数据包的源地址。</li><li>目的NAT(Destination NAT,DNAT):修改数据包的目的地址。</li></ol><h2 id="数据连接层(数据链路层)(Data-Link-Layer)"><a href="#数据连接层(数据链路层)(Data-Link-Layer)" class="headerlink" title="数据连接层(数据链路层)(Data Link Layer)"></a>数据连接层(数据链路层)(Data Link Layer)</h2><p>连接层用来解读0和1的电信号,确定0/1的分组方式。</p><p>在两个网络实体之间提供数据链路连接的创建、维持和释放管理。构成数据链路数据单元(frame:数据帧或讯框),并对帧定界、同步、收发顺序的控制。传输过程中的网络流量控制、差错检测和差错控制等方面。在物理层的基础上向网络层提供服务,其最基本的职责是将源自网络层的数据可靠的传输到相邻节点的目标网络层。主要以以太网为主。</p><h3 id="以太网"><a href="#以太网" class="headerlink" title="以太网"></a>以太网</h3><p>以太网规定,一组电信号构成一个数据包,叫做”帧”(Frame)。每一帧分成两个部分:标头(Head)和数据(Data)。</p><p>“标头”包含数据包的一些说明项,比如发送者、接受者、数据类型等等;”数据”则是数据包的具体内容。</p><p>“标头”的长度,固定为18字节。”数据”的长度,最短为46字节,最长为1500字节。因此,整个”帧”最短为64字节,最长为1518字节。如果数据很长,就必须分割成多个帧进行发送。</p><h3 id="MAC地址"><a href="#MAC地址" class="headerlink" title="MAC地址"></a>MAC地址</h3><p>以太网数据包的”标头”,包含了发送者和接受者的信息。那么,发送者和接受者是如何标识呢?</p><p>以太网规定,连入网络的所有设备,都必须具有”网卡”接口。数据包必须是从一块网卡,传送到另一块网卡。网卡的地址,就是数据包的发送地址和接收地址,这叫做MAC地址。</p><h3 id="广播"><a href="#广播" class="headerlink" title="广播"></a>广播</h3><p>首先,一块网卡怎么会知道另一块网卡的MAC地址?</p><p>回答是有一种ARP协议,可以解决这个问题。这个留到后面介绍,这里只需要知道,以太网数据包必须知道接收方的MAC地址,然后才能发送。</p><p>其次,就算有了MAC地址,系统怎样才能把数据包准确送到接收方?</p><p>回答是以太网采用了一种很”原始”的方式,它不是把数据包准确送到接收方,而是向本网络内所有计算机发送,让每台计算机自己判断,是否为接收方。</p><h2 id="物理层(Physical-Layer)"><a href="#物理层(Physical-Layer)" class="headerlink" title="物理层(Physical Layer)"></a>物理层(Physical Layer)</h2><p>就是实际上电脑间连接的介质,比如网线、光纤、电缆等,主要规定了网络的电气特性,负责传输二进制形式的数据。对应协议:ISO2110,IEEE802,IEEE802.2;</p><h2 id="数据处理流程"><a href="#数据处理流程" class="headerlink" title="数据处理流程"></a>数据处理流程</h2><p>下图以用户 a 向用户 b 发送邮件为例子:</p><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541909824/WX20181111-121645_2x.png" alt="数据处理流程"></p><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ol><li><a href="https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82" target="_blank" rel="noopener">https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82</a></li><li><a href="https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82" target="_blank" rel="noopener">https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82</a></li><li><a href="https://blog.csdn.net/zhshulin/article/details/62888061" target="_blank" rel="noopener">https://blog.csdn.net/zhshulin/article/details/62888061</a></li><li><a href="https://juejin.im/post/5a069b6d51882509e5432656" target="_blank" rel="noopener">https://juejin.im/post/5a069b6d51882509e5432656</a></li><li><a href="http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html</a></li></ol>]]></content>
<summary type="html">
<p>互联网协议分为好几层,每一层都有自己的功能定位,一般分为5层比较容易理解。</p>
<h2 id="应用层(Application-Layer)"><a href="#应用层(Application-Layer)" class="headerlink" title="应用层
</summary>
<category term="网络协议" scheme="https://scoolor.github.io/tags/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/"/>
<category term="Internet Protocol" scheme="https://scoolor.github.io/tags/Internet-Protocol/"/>
</entry>
<entry>
<title>DNS为什么既使用TCP又使用UDP?</title>
<link href="https://scoolor.github.io/2018/11/10/dns-udp-tcp/"/>
<id>https://scoolor.github.io/2018/11/10/dns-udp-tcp/</id>
<published>2018-11-10T15:43:46.000Z</published>
<updated>2018-11-11T01:14:16.310Z</updated>
<content type="html"><![CDATA[<p>在 <a href="https://scoolor.github.io/2018/11/10/dns/">https://scoolor.github.io/2018/11/10/dns/</a> 一文中简单整理了DNS协议的一些知识,其中涉及到DNS协议同时会占用53端口,且同时使用UDP和TCP协议,我们使用Wireshark抓包,看到在解析时仅仅使用了UDP协议,这是为什么呢?本文简要说明一下。</p><h2 id="TCP与UDP协议"><a href="#TCP与UDP协议" class="headerlink" title="TCP与UDP协议"></a>TCP与UDP协议</h2><p>首先简要介绍一下TCP和UDP协议。</p><p>TCP(Transmission Control Protocol,传输控制协议)是一种<em>面向连接的协议</em>,提供可靠的数据传输,一般服务质量要求比较高的情况,使用这个协议。</p><p>UDP(User Datagram Protocol,用户数据报协议)是用户数据报协议,是一种<em>无连接的传输层协议</em>,提供面向事务的简单不可靠信息传送服务。 </p><h3 id="区别如下"><a href="#区别如下" class="headerlink" title="区别如下"></a>区别如下</h3><p>TCP 是面向连接的传输控制协议,而UDP提供了无链接的数据报服务,类似电话与短信;</p><p>TCP 面向连接,提供可靠的数据服务;</p><p>TCP首部开销20字节,UDP首部开销8字节;</p><p>TCP逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道;</p><p>UDP没有拥塞机制,因此网络出现拥堵不会使源主机的发送效率降低(有利于实时会议视频等);</p><p>TCP的连接只能是点到点的,UDP支持一对一,多对一,多对多的交互通信;</p><p>UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境;</p><h3 id="简要总结"><a href="#简要总结" class="headerlink" title="简要总结"></a>简要总结</h3><p>TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。</p><p>UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。</p><p>既然UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?</p><p>其实不然,在有些情况下UDP协议可能会变得非常有用。</p><p>因为UDP具有TCP所望尘莫及的速度优势。虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,无疑使速度受到严重的影响。反观UDP由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。 </p><h2 id="为什么DNS既使用TCP又使用UDP?"><a href="#为什么DNS既使用TCP又使用UDP?" class="headerlink" title="为什么DNS既使用TCP又使用UDP?"></a>为什么DNS既使用TCP又使用UDP?</h2><h3 id="DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;"><a href="#DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;" class="headerlink" title="DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;"></a>DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;</h3><p>DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。 </p><p>区域传输是DNS的事务,对准确性要求比较高,而且会产生大于512字节的数据包,因此使用TCP协议。</p><h3 id="为什么既使用TCP又使用UDP?"><a href="#为什么既使用TCP又使用UDP?" class="headerlink" title="为什么既使用TCP又使用UDP?"></a>为什么既使用TCP又使用UDP?</h3><p>首先了解一下TCP与UDP传送字节的长度限制。</p><p><em>UDP报文的最大长度为512字节,而TCP则允许报文长度超过512字节</em>。当DNS查询超过512字节时,协议的TC标志出现删除标志,这时则使用TCP发送。通常传统的UDP报文一般不会大于512字节。</p><h3 id="区域传送时使用TCP,主要有一下两点考虑"><a href="#区域传送时使用TCP,主要有一下两点考虑" class="headerlink" title="区域传送时使用TCP,主要有一下两点考虑"></a>区域传送时使用TCP,主要有一下两点考虑</h3><ol><li>辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。 </li><li>TCP是一种可靠的连接,保证了数据的准确性。 </li></ol><h3 id="域名解析时使用UDP协议"><a href="#域名解析时使用UDP协议" class="headerlink" title="域名解析时使用UDP协议"></a>域名解析时使用UDP协议</h3><p>客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>大多数情况下,DNS解析请求和响应都很小,使用UDP协议更加高效,虽然没有TCP可靠,但是速度快,消耗的系统资源更少,非常适合少量数据包的传输。<br>一些DNS事务,比如区域传输或其他附加查询,可能会产生大于512字节的数据包,因此使用TCP更加可靠,使用TCP会减少丢包和重新发包的情况,因此更加可靠与高效。</p><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ol><li><a href="http://benbenxiongyuan.iteye.com/blog/1088085" target="_blank" rel="noopener">http://benbenxiongyuan.iteye.com/blog/1088085</a></li><li><a href="https://www.cnblogs.com/549294286/p/5172435.html" target="_blank" rel="noopener">https://www.cnblogs.com/549294286/p/5172435.html</a></li><li><a href="https://www.quora.com/When-does-DNS-use-TCP-instead-of-UDP-Why" target="_blank" rel="noopener">https://www.quora.com/When-does-DNS-use-TCP-instead-of-UDP-Why</a></li></ol>]]></content>
<summary type="html">
<p>在 <a href="https://scoolor.github.io/2018/11/10/dns/">https://scoolor.github.io/2018/11/10/dns/</a> 一文中简单整理了DNS协议的一些知识,其中涉及到DNS协议同时会占用53端
</summary>
<category term="dns" scheme="https://scoolor.github.io/tags/dns/"/>
<category term="tcp" scheme="https://scoolor.github.io/tags/tcp/"/>
<category term="udp" scheme="https://scoolor.github.io/tags/udp/"/>
</entry>
<entry>
<title>DNS域名系统</title>
<link href="https://scoolor.github.io/2018/11/10/dns/"/>
<id>https://scoolor.github.io/2018/11/10/dns/</id>
<published>2018-11-10T13:48:02.000Z</published>
<updated>2018-11-10T15:41:34.670Z</updated>
<content type="html"><![CDATA[<p>域名系统(英文:Domain Name System,缩写:DNS),是互联网的重要基础协议,作用就是根据域名查出对应的IP地址。</p><p>它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。</p><p>DNS同时使用TCP和UDP协议,端口53。</p><h2 id="查询过程"><a href="#查询过程" class="headerlink" title="查询过程"></a>查询过程</h2><p>虽然dns只返回一个ip地址,但是查询过程非常复杂,一般分为多个步骤。</p><p>linux命令行工具可以显示整个查询过程。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dig math.stackexchange.com</span><br></pre></td></tr></table></figure><p>输出内容如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">; <<>> DiG 9.9.5-9+deb8u16-Debian <<>> math.stackexchange.com</span><br><span class="line">;; global options: +cmd</span><br><span class="line">;; Got answer:</span><br><span class="line">;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19662</span><br><span class="line">;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1</span><br><span class="line"></span><br><span class="line">;; OPT PSEUDOSECTION:</span><br><span class="line">; EDNS: version: 0, flags:; udp: 512</span><br><span class="line">;; QUESTION SECTION:</span><br><span class="line">;math.stackexchange.com.INA</span><br><span class="line"></span><br><span class="line">;; ANSWER SECTION:</span><br><span class="line">math.stackexchange.com.68INA151.101.1.69</span><br><span class="line">math.stackexchange.com.68INA151.101.65.69</span><br><span class="line">math.stackexchange.com.68INA151.101.129.69</span><br><span class="line">math.stackexchange.com.68INA151.101.193.69</span><br><span class="line"></span><br><span class="line">;; Query time: 227 msec</span><br><span class="line">;; SERVER: 10.0.2.3#53(10.0.2.3)</span><br><span class="line">;; WHEN: Sat Nov 10 22:03:00 CST 2018</span><br><span class="line">;; MSG SIZE rcvd: 115</span><br></pre></td></tr></table></figure><ul><li>第一段是查询参数和统计;</li><li>第二段是查询内容,查询域名math.stackexchange.com的A记录,A是address的缩写;</li><li>第三段是DNS服务器的答复;上面结果显示,math.stackexchange.com有四个A记录,即四个IP地址。68是TTL值(Time to live 的缩写),表示缓存时间,即68秒之内不用重新查询;</li><li>第四段是DNS服务器的一些传输信息。</li></ul><h2 id="DNS服务器"><a href="#DNS服务器" class="headerlink" title="DNS服务器"></a>DNS服务器</h2><p>DNS服务器的IP地址,有可能是动态的,每次上网时由网关分配,这叫做DHCP机制。</p><p>也有可能是事先指定的固定地址。Linux系统里面,DNS服务器的IP地址保存在/etc/resolv.conf文件。</p><p>上例的DNS服务器是10.0.2.3,这是一个内网地址。有一些公网的DNS服务器,也可以使用,其中最有名的就是Google的8.8.8.8和Level 3的4.2.2.2。</p><p>dig命令有一个@参数,显示向指定DNS服务器查询的结果。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ dig @4.2.2.2 math.stackexchange.com</span><br></pre></td></tr></table></figure><h2 id="域名的层级"><a href="#域名的层级" class="headerlink" title="域名的层级"></a>域名的层级</h2><p>DNS查询有两种方式:递归和迭代。DNS客户端设置使用的DNS服务器一般都是递归服务器,它负责全权处理客户端的DNS查询请求,直到返回最终结果。而DNS服务器之间一般采用迭代查询方式。</p><p>DNS服务器怎么会知道每个域名的IP地址呢?答案是分级查询。</p><p>请仔细看前面的例子,每个域名的尾部都多了一个点。</p><p>比如,域名<code>math.stackexchange.com</code>显示为<code>math.stackexchange.com.</code>。这不是疏忽,而是所有域名的尾部,实际上都有一个根域名。</p><p>举例来说,<code>www.example.com</code>真正的域名是<code>www.example.com.root</code>,简写为<code>www.example.com.</code>。因为,根域名.root对于所有域名都是一样的,所以平时是省略的。</p><p>根域名的下一级,叫做”顶级域名”(top-level domain,缩写为TLD),比如.com、.net;再下一级叫做”次级域名”(second-level domain,缩写为SLD),比如<a href="http://www.example.com里面的.example,这一级域名是用户可以注册的;再下一级是主机名(host),比如www.example.com里面的www,又称为"三级域名",这是用户在自己的域里面为服务器分配的名称,是用户可以任意分配的。" target="_blank" rel="noopener">www.example.com里面的.example,这一级域名是用户可以注册的;再下一级是主机名(host),比如www.example.com里面的www,又称为"三级域名",这是用户在自己的域里面为服务器分配的名称,是用户可以任意分配的。</a></p><p>总结一下,域名的层级结构如下。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">主机名.次级域名.顶级域名.根域名</span><br><span class="line"># 即</span><br><span class="line">host.sld.tld.root</span><br></pre></td></tr></table></figure><h2 id="DNS-的记录类型"><a href="#DNS-的记录类型" class="headerlink" title="DNS 的记录类型"></a>DNS 的记录类型</h2><p>域名与IP之间的对应关系,称为”记录”(record)。根据使用场景,”记录”可以分成不同的类型(type),前面已经看到了有A记录和NS记录。</p><p>常见的DNS记录类型如下。</p><ol><li>A:主机记录(Address),返回域名指向的IP地址。</li><li>NS:名字服务器,本域的服务器名,域名服务器记录(Name Server),返回保存下一级域名信息的服务器地址。该记录只能设置为域名,不能设置为IP地址。</li><li>MX:邮件记录(Mail eXchange),返回接收电子邮件的服务器地址。</li><li>CNAME:别名记录,规范名称记录(Canonical Name),返回另一个域名,即当前查询的域名是另一个域名的跳转。</li><li>PTR:逆向查询记录(Pointer Record),只用于从IP地址查询域名。</li><li>IPv6主机记录(AAAA记录): RFC 3596定义,与A记录对应,用于将特定的主机名映射到一个主机的IPv6地址。</li></ol><p>CNAME 记录主要用于域名的内部跳转,为服务器配置提供灵活性,用户感知不到。<br>由于CNAME记录就是一个替换,所以域名一旦设置CNAME记录以后,就不能再设置其他记录了(比如A记录和MX记录)。</p><p>NS记录(Name Server的缩写),即哪些服务器负责管理域名的DNS记录。</p><h2 id="DNS协议报文"><a href="#DNS协议报文" class="headerlink" title="DNS协议报文"></a>DNS协议报文</h2><p>dns请求和应答都是用相同的报文格式,分成5个段(有的报文段在不同的情况下可能为空),如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">+---------------------+</span><br><span class="line">| Header | 报文头</span><br><span class="line">+---------------------+</span><br><span class="line">| Question | 查询的问题</span><br><span class="line">+---------------------+</span><br><span class="line">| Answer | 应答</span><br><span class="line">+---------------------+</span><br><span class="line">| Authority | 授权应答</span><br><span class="line">+---------------------+</span><br><span class="line">| Additional | 附加信息</span><br><span class="line">+---------------------+</span><br></pre></td></tr></table></figure><p>Header段是必须存在的,它定义了报文是请求还是应答,也定义了其他段是否需要存在,以及是标准查询还是其他。 </p><h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2><p>执行 <code>dig baidu.com</code>,使用wireshark抓包,查看请求与响应报文,本次请求抓包看到使用的是UDP协议。那么为什么只是用了UDP协议呢?留个悬念。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dig baidu.com</span><br></pre></td></tr></table></figure><p>返回解决如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">; <<>> DiG 9.9.5-9+deb8u16-Debian <<>> baidu.com</span><br><span class="line">;; global options: +cmd</span><br><span class="line">;; Got answer:</span><br><span class="line">;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26178</span><br><span class="line">;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1</span><br><span class="line"></span><br><span class="line">;; OPT PSEUDOSECTION:</span><br><span class="line">; EDNS: version: 0, flags:; udp: 512</span><br><span class="line">;; QUESTION SECTION:</span><br><span class="line">;baidu.com.INA</span><br><span class="line"></span><br><span class="line">;; ANSWER SECTION:</span><br><span class="line">baidu.com.195INA220.181.57.216</span><br><span class="line">baidu.com.195INA123.125.115.110</span><br><span class="line"></span><br><span class="line">;; Query time: 226 msec</span><br><span class="line">;; SERVER: 10.0.2.3#53(10.0.2.3)</span><br><span class="line">;; WHEN: Sat Nov 10 23:12:39 CST 2018</span><br><span class="line">;; MSG SIZE rcvd: 70</span><br></pre></td></tr></table></figure><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541863705/1541863423326.jpg" alt="wireshark"></p><p>请求报文:<br><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541863705/1541863294628.jpg" alt="wireshark请求"></p><p>响应报文:<br><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541863705/1541863343065.jpg" alt="wireshark响应"></p><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ol><li><a href="https://zh.wikipedia.org/zh-hans/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F" target="_blank" rel="noopener">https://zh.wikipedia.org/zh-hans/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F</a></li><li><a href="http://www.ruanyifeng.com/blog/2016/06/dns.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2016/06/dns.html</a></li></ol>]]></content>
<summary type="html">
<p>域名系统(英文:Domain Name System,缩写:DNS),是互联网的重要基础协议,作用就是根据域名查出对应的IP地址。</p>
<p>它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。</p>
<p>DNS同时使用TCP和UDP协议,
</summary>
<category term="dns" scheme="https://scoolor.github.io/tags/dns/"/>
</entry>
<entry>
<title>网卡混杂模式介绍</title>
<link href="https://scoolor.github.io/2018/11/10/network-promiscuous/"/>
<id>https://scoolor.github.io/2018/11/10/network-promiscuous/</id>
<published>2018-11-10T12:52:37.000Z</published>
<updated>2018-11-10T13:12:51.590Z</updated>
<content type="html"><![CDATA[<p>网卡有多种工作模式,默认情况下网卡只把本机的包(包括广播包)传递给上层程序,其他的包一律丢弃。混杂模式是指网卡能接受所有通过它的数据流,不管什么格式,什么地址(即不校验mac地址)。</p><p>一般来说,混杂模式不会影响网卡的正常工作,多在网络监听工具上使用。</p><h2 id="网卡的工作模式"><a href="#网卡的工作模式" class="headerlink" title="网卡的工作模式"></a>网卡的工作模式</h2><p>网卡具有如下几种工作模式:</p><ol><li>广播模式(Broad Cast Model):它的物理地址(MAC)地址是 0Xffffff 的帧为广播帧,工作在广播模式的网卡接收广播帧;</li><li>多播传送(MultiCast Model):多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员;</li><li>直接模式(Direct Model):工作在直接模式下的网卡只接收目地址是自己 Mac地址的帧;</li><li>混杂模式(Promiscuous Model):工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的。</li></ol><p>网卡的缺省工作模式包含广播模式和直接模式,即它只接收广播帧和发给自己的帧。如果采用混杂模式,一个站点的网卡将接受同一网络内所有站点所发送的数据包这样就可以到达对于网络信息监视捕获的目的。</p><h2 id="Linux下网卡混杂模式设置方法"><a href="#Linux下网卡混杂模式设置方法" class="headerlink" title="Linux下网卡混杂模式设置方法"></a>Linux下网卡混杂模式设置方法</h2><h3 id="命令实现"><a href="#命令实现" class="headerlink" title="命令实现"></a>命令实现</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ifconfig eth0 promisc #set</span><br><span class="line">ifconfig eth0 -promisc #unset</span><br></pre></td></tr></table></figure><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ol><li><a href="https://blog.csdn.net/JAZZSOLDIER/article/details/52368020" target="_blank" rel="noopener">https://blog.csdn.net/JAZZSOLDIER/article/details/52368020</a></li></ol>]]></content>
<summary type="html">
<p>网卡有多种工作模式,默认情况下网卡只把本机的包(包括广播包)传递给上层程序,其他的包一律丢弃。混杂模式是指网卡能接受所有通过它的数据流,不管什么格式,什么地址(即不校验mac地址)。</p>
<p>一般来说,混杂模式不会影响网卡的正常工作,多在网络监听工具上使用。</p>
</summary>
<category term="Linux" scheme="https://scoolor.github.io/tags/Linux/"/>
</entry>
<entry>
<title>为什么charles/fiddler可以明文抓取https</title>
<link href="https://scoolor.github.io/2018/11/10/charles-https/"/>
<id>https://scoolor.github.io/2018/11/10/charles-https/</id>
<published>2018-11-10T01:06:11.000Z</published>
<updated>2018-11-10T02:33:27.150Z</updated>
<content type="html"><![CDATA[<p>阅读本文首先需要了解https的基本原理,可以参考 <a href="https://scoolor.github.io/2018/09/03/https/">https://scoolor.github.io/2018/09/03/https/</a></p><p>理解https的抓包原理,首先要理解中间人的概念,也就是MITM。</p><h2 id="MITM介绍"><a href="#MITM介绍" class="headerlink" title="MITM介绍"></a>MITM介绍</h2><p>MITM(Man-In-The-Middle,中间人),能够与网络通信的两端分别创建连接,交换其收到的数据,使得通讯两端都认为自己直接与对方对话,实际上整个会话被中间人控制。</p><p>简而言之,就是在真正的服务端看来,中间人是客户端;而对真正的客户端来说,中间人是服务端。</p><h2 id="主要原理介绍"><a href="#主要原理介绍" class="headerlink" title="主要原理介绍"></a>主要原理介绍</h2><p>常见的http/https抓包工具charles/fiddler的工作原理与中间人一致,都是通过创建本地的proxy服务,然后修改浏览器的proxy配置来达到拦截流量的目的。</p><p>对于https连接来说,中间人要满足以下两点,才能实现真正的明文代理:</p><ol><li>中间人,作为客户端与真实服务端建立连接这一步不会有问题,因为服务端不会校验客户端的身份;</li><li>中间人,作为服务端与真实客户端建立连接,这里会有客户端信任服务端的问题,也就是服务端必须有对应域名的私钥;</li></ol><p>中间人要拿到私钥只能通过如下方式:</p><ol><li>去网站服务端拿到私钥;</li><li>去CA处拿域名签发私钥;</li><li>自己签发证书,切要被浏览器信任;</li></ol><p>不用解释,抓包工具只能使用第三种方式取得中间人的身份。</p><p>使用抓包工具进行https抓包的时候,需要在客户端安装charles/fiddler的根证书,这里实际上起认证中心(CA)的作用。</p><p>charles能够抓包的关键是客户端会往系统受信任的根证书列表中导入charles生成的证书,而这个证书会被浏览器信任,也就是charles给自己创建了一个认证中心CA,客户端拿着中间人签发的证书去中间人自己的CA去认证,当然认为这个证书是有效的。因此代理作为中间人取得了客户端的信任。</p><h2 id="简单总结"><a href="#简单总结" class="headerlink" title="简单总结"></a>简单总结</h2><p>charle/fiddler抓包https时,作为中间人,与客户端连接时,中间人自己生成证书,并且使用自己的CA进行签名,取得客户端的信任;与服务端连接时,中间人接受服务端的证书,与服务端不存在信任问题。因此就实现了https的代理。</p>]]></content>
<summary type="html">
<p>阅读本文首先需要了解https的基本原理,可以参考 <a href="https://scoolor.github.io/2018/09/03/https/">https://scoolor.github.io/2018/09/03/https/</a></p>
<p>理解
</summary>
<category term="charle" scheme="https://scoolor.github.io/tags/charle/"/>
<category term="https" scheme="https://scoolor.github.io/tags/https/"/>
</entry>
<entry>
<title>Linux理解-一切皆文件</title>
<link href="https://scoolor.github.io/2018/11/08/linux-everything-is-file/"/>
<id>https://scoolor.github.io/2018/11/08/linux-everything-is-file/</id>
<published>2018-11-08T00:34:42.000Z</published>
<updated>2018-11-08T01:01:01.080Z</updated>
<content type="html"><![CDATA[<p>linux/unix下的哲学核心思想是‘一切皆文件’。<br>“一切皆文件”,指的是,对所有文件(目录、字符设备、块设备、套接字、打印机、进程、线程、管道等)操作,读写都可用fopen()/fclose()/fwrite()/fread()等函数进行处理。屏蔽了硬件的区别,所有设备都抽象成文件,提供统一的接口给用户。虽然类型各不相同,但是对其提供的却是同一套操作界面。更进一步,对文件的操作也可以跨文件系统执行。</p><p>那么如何操作一个已经打开的文件?<br>文件描述符(file descriptor),简称fd。这里就使用到了“文件描述符”,它是一个对应某个已经打开的文件的索引(非负整数)。</p><h2 id="文件类型"><a href="#文件类型" class="headerlink" title="文件类型"></a>文件类型</h2><table><thead><tr><th>类型</th><th>简称</th><th>描述</th></tr></thead><tbody><tr><td>普通文件</td><td>-,Normal File</td><td>如mp4、pdf、html log;<br>用户可以根据访问权限对普通文件进行查看、更改和删除,包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-]</td></tr><tr><td>目录文件</td><td>d,directory file</td><td>/usr/ /home/ <br>目录文件包含了各自目录下的文件名和指向这些文件的指针,打开目录事实上就是打开目录文件,只要有访问权限,就可以随意访问这些目录下的文件。能用#cd命令进入的。第一个属性为[d],例如 [drwxrwxrwx]</td></tr><tr><td>硬链接</td><td>-,hard links</td><td>若一个inode号对应多个文件名,则称这些文件为硬链接。硬链接就是同一个文件使用了多个别名删除时,只会删除链接, 不会删除文件;<br>硬链接的局限性:1.不能引用自身文件系统以外的文件,即不能引用其他分区的文件;2.无法引用目录;</td></tr><tr><td>符号链接(软链接)</td><td>l,symbolic link</td><td>若文件用户数据块中存放的内容是另一文件的路径名的指向,则该文件就是软连接,克服硬链接的局限性, 类似于快捷方式,使用与硬链接相同。</td></tr><tr><td>字符设备文件</td><td>c,char</td><td>文件一般隐藏在/dev目录下,在进行设备读取和外设交互时会被使用到<br>即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c]。<br>#/dev/tty的属性是 crw-rw-rw-,注意前面第一个字 c,这表示字符设备文件</td></tr><tr><td>块设备文件</td><td>b,block</td><td>存储数据以供系统存取的接口设备,简单而言就是硬盘。<br># /dev/hda1 的属性是 brw-r—– ,注意前面的第一个字符是b,这表示块设备,比如硬盘,光驱等设备<br>系统中的所有设备要么是块设备文件,要么是字符设备文件,无一例外</td></tr><tr><td>FIFO管道文件</td><td>p,pipe</td><td>管道文件主要用于进程间通讯。FIFO解决多个程序同时存取一个文件所造成的错误。比如使用mkfifo命令可以创建一个FIFO文件,启用一个进程A从FIFO文件里读数据,启动进程B往FIFO里写数据,先进先出,随写随读。<br># pipe</td></tr><tr><td>套接字</td><td>s,socket</td><td>以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。用于进程间的网络通信,也可以用于本机之间的非网络通信,第一个属性为 [s],这些文件一般隐藏在/var/run目录下,证明着相关进程的存在</td></tr></tbody></table>]]></content>
<summary type="html">
<p>linux/unix下的哲学核心思想是‘一切皆文件’。<br>“一切皆文件”,指的是,对所有文件(目录、字符设备、块设备、套接字、打印机、进程、线程、管道等)操作,读写都可用fopen()/fclose()/fwrite()/fread()等函数进行处理。屏蔽了硬件的区别,
</summary>
<category term="Linux" scheme="https://scoolor.github.io/tags/Linux/"/>
</entry>
<entry>
<title>理解 Linux inode</title>
<link href="https://scoolor.github.io/2018/11/07/linux-inode/"/>
<id>https://scoolor.github.io/2018/11/07/linux-inode/</id>
<published>2018-11-07T15:44:39.000Z</published>
<updated>2018-11-07T16:43:37.780Z</updated>
<content type="html"><![CDATA[<h2 id="inode-是什么?"><a href="#inode-是什么?" class="headerlink" title="inode 是什么?"></a>inode 是什么?</h2><p>理解inode,要从文件储存说起。</p><p>文件储存在硬盘上,硬盘的最小存储单位叫做”扇区”(Sector)。每个扇区储存512字节(相当于0.5KB)。</p><p>操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是4KB,即连续八个 sector组成一个 block。</p><p>文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。</p><h2 id="inode-包含的内容"><a href="#inode-包含的内容" class="headerlink" title="inode 包含的内容"></a>inode 包含的内容</h2><p>inode包含文件的元信息,具体来说有以下内容:</p><ul><li>文件的字节数</li><li>文件拥有者的User ID</li><li>文件的Group ID</li><li>文件的读、写、执行权限</li><li>文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。</li><li>链接数,即有多少文件名指向这个inode</li><li>文件数据block的位置</li></ul><p>可以用stat命令,查看某个文件的inode信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">stat example.txt</span><br></pre></td></tr></table></figure><h2 id="inode-的大小"><a href="#inode-的大小" class="headerlink" title="inode 的大小"></a>inode 的大小</h2><p>inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。</p><p>每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。</p><p>查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">df -i</span><br></pre></td></tr></table></figure><h2 id="inode号码"><a href="#inode号码" class="headerlink" title="inode号码"></a>inode号码</h2><p>每个inode都有一个号码,操作系统用inode号码来识别不同的文件。</p><p>这里值得重复一遍,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。</p><p>使用ls -i命令,可以看到文件名对应的inode号码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -i example.txt</span><br></pre></td></tr></table></figure><h2 id="目录文件"><a href="#目录文件" class="headerlink" title="目录文件"></a>目录文件</h2><p>Unix/Linux系统中,目录(directory)也是一种文件。打开目录,实际上就是打开目录文件。</p><p>目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。</p><h2 id="硬链接"><a href="#硬链接" class="headerlink" title="硬链接"></a>硬链接</h2><p>一般情况下,文件名和inode号码是”一一对应”关系,每个inode号码对应一个文件名。但是,Unix/Linux系统允许,多个文件名指向同一个inode号码。这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为”硬链接”(hard link)。</p><h2 id="软链接"><a href="#软链接" class="headerlink" title="软链接"></a>软链接</h2><p>除了硬链接以外,还有一种特殊情况。文件A和文件B的inode号码虽然不一样,但是文件A的内容是文件B的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的”软链接”(soft link)或者”符号链接(symbolic link)。<br><code>ln -s</code> 命令可以创建软链接。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ln -s a b</span><br></pre></td></tr></table></figure><h2 id="操作系统读取磁盘文件的流程"><a href="#操作系统读取磁盘文件的流程" class="headerlink" title="操作系统读取磁盘文件的流程"></a>操作系统读取磁盘文件的流程</h2><ol><li>根据dictionary的对应关系找到该文件的inode(dictionary简单理解就是一张表,存储文件到inode号的映射)</li><li>根据inode,找到inodeTable</li><li>根据inodeTable中的对应关系,找到对应硬盘中的block</li><li>从硬盘block中读取文件</li></ol><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1541608962/79A96E88-8B39-485E-96BF-11269CDA635D.png" alt="操作系统读取磁盘文件的流程"></p>]]></content>
<summary type="html">
<h2 id="inode-是什么?"><a href="#inode-是什么?" class="headerlink" title="inode 是什么?"></a>inode 是什么?</h2><p>理解inode,要从文件储存说起。</p>
<p>文件储存在硬盘上,硬盘的最
</summary>
<category term="linux" scheme="https://scoolor.github.io/tags/linux/"/>
</entry>
<entry>
<title>Linux 设备分类</title>
<link href="https://scoolor.github.io/2018/11/07/linux-device/"/>
<id>https://scoolor.github.io/2018/11/07/linux-device/</id>
<published>2018-11-07T14:18:33.000Z</published>
<updated>2018-11-07T15:47:02.470Z</updated>
<content type="html"><![CDATA[<p>Linux中设备分为:字符设备、块设备、网络设备、伪设备。</p><h2 id="字符设备"><a href="#字符设备" class="headerlink" title="字符设备"></a>字符设备</h2><p>字符设备是指每次与系统传输1个字符的设备。这些设备节点通常为传真、虚拟终端和串口调制解调器之类设备提供流通信服务,它通常不支持随机存取数据。</p><p>字符设备在实现时,大多不使用缓存器。系统直接从设备读取/写入每一个字符。</p><h2 id="块设备"><a href="#块设备" class="headerlink" title="块设备"></a>块设备</h2><p>块设备是指与系统间用块的方式移动数据的设备。这些设备节点通常代表可寻址设备。块设备的数据可以随机地被访问,而且从人类用户的观点看,传送任何数据块所需的时间都是较少而且是大致相同的。块设备的典型例子是硬盘、软盘。块设备一般情况下是带缓冲区的。</p><p>当程序向设备发送了读取或者写入数据的请求时,系统把数据中的每一个字符存储在适当的缓存中。当缓存被填满时,会采取适当的操作(把数据传走),而后系统清空缓存。</p><h2 id="网络设备"><a href="#网络设备" class="headerlink" title="网络设备"></a>网络设备</h2><p>网络设备是特殊设备的驱动,它负责接收和发送帧数据,可能是物理帧,也可能是ip数据包,这些特性都有网络驱动决定。它并不存在于/dev下面,所以与一般的设备不同。网络设备是一个net_device结构,并通过register_netdev注册到系统里,最后通过ifconfig -a的命令就能看到。</p><h1 id="伪设备"><a href="#伪设备" class="headerlink" title="伪设备"></a>伪设备</h1><p>在类Unix操作系统中,设备节点并不一定要对应物理设备,没有这种对应关系的设备是伪设备,经常用到的伪设备如下:</p><ul><li>/dev/null<br>接受并丢弃所有输入;即不产生任何输出。</li><li>/dev/full<br>永远在被填满状态的设备。</li><li>/dev/loop<br>Loop设备</li><li>/dev/zero<br>产生连续的NUL字元的串流(数值为0)。</li><li>/dev/random<br>产生一个虚假随机的任意长度字元串流(Blocking)。</li><li>/dev/urandom<br>产生一个虚假随机的任意长度字元串流(Non-Blocking)。</li></ul>]]></content>
<summary type="html">
<p>Linux中设备分为:字符设备、块设备、网络设备、伪设备。</p>
<h2 id="字符设备"><a href="#字符设备" class="headerlink" title="字符设备"></a>字符设备</h2><p>字符设备是指每次与系统传输1个字符的设备。这些设备
</summary>
<category term="linux" scheme="https://scoolor.github.io/tags/linux/"/>
</entry>
<entry>
<title>base64简介</title>
<link href="https://scoolor.github.io/2018/09/03/base64/"/>
<id>https://scoolor.github.io/2018/09/03/base64/</id>
<published>2018-09-03T14:26:40.000Z</published>
<updated>2018-09-03T15:12:40.720Z</updated>
<content type="html"><![CDATA[<p>Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方为64,所以每6个位(bit)为一个单元,对应某个可打印字符。3个字节有24个位,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。编码后的数据比原始数据略长,为原来的 1.33倍。Base64是一种可逆的编码方式,从编码的方式即可逆推出解码的方式。</p><h2 id="适用场景"><a href="#适用场景" class="headerlink" title="适用场景"></a>适用场景</h2><p>Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。</p><h2 id="Base64索引表"><a href="#Base64索引表" class="headerlink" title="Base64索引表"></a>Base64索引表</h2><p>十进制对应表0-63。<br><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1535986414/1535986368851.jpg" alt="Base64索引表"></p><h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h2><ol><li>编码 ‘Man’</li></ol><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1535986618/1535986568295.jpg" alt="Man编码示例"></p><ol start="2"><li>如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:先使用0字节值在末尾补足,使其能够被3整除,然后再进行Base64的编码。在编码后的Base64文本后加上一个或两个=号,代表补足的字节数。也就是说,当最后剩余两个八位字节(2个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;如果最后剩余一个八位字节(1个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。 参考下表:</li></ol><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1535986619/1535986600489.jpg" alt="Base64编码补齐示例"></p><ol start="3"><li>汉字’严’</li></ol><p>汉字”严”如何转化成Base64编码?</p><p>这里需要注意,汉字本身可以有多种编码,比如gb2312、utf-8、gbk等等,每一种编码的Base64对应值都不一样。下面的例子以utf-8为例。</p><p>首先,”严”的utf-8编码为E4B8A5,写成二进制就是三字节的”11100100 10111000 10100101”。将这个24位的二进制字符串,按照第3节中的规则,转换成四组一共32位的二进制值”00111001 00001011 00100010 00100101”,相应的十进制数为57、11、34、37,它们对应的Base64值就为5、L、i、l。</p><p>所以,汉字”严”(utf-8编码)的Base64值就是5Lil。</p><h2 id="在URL中的应用"><a href="#在URL中的应用" class="headerlink" title="在URL中的应用"></a>在URL中的应用</h2><p>标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的/和+字符变为形如%XX的形式。</p><p>为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充=号,并将标准Base64中的+和/分别改成了-和_,称为”url safe”的base64编码,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://zh.wikipedia.org/zh-hans/Base64" target="_blank" rel="noopener">https://zh.wikipedia.org/zh-hans/Base64</a></li><li><a href="http://www.ruanyifeng.com/blog/2008/06/base64.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2008/06/base64.html</a></li></ul>]]></content>
<summary type="html">
<p>Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方为64,所以每6个位(bit)为一个单元,对应某个可打印字符。3个字节有24个位,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。编码后的数据比原始数据略长,为原来的 1.33倍
</summary>
<category term="编码" scheme="https://scoolor.github.io/tags/%E7%BC%96%E7%A0%81/"/>
<category term="base64" scheme="https://scoolor.github.io/tags/base64/"/>
</entry>
<entry>
<title>理解HTTPS</title>
<link href="https://scoolor.github.io/2018/09/03/https/"/>
<id>https://scoolor.github.io/2018/09/03/https/</id>
<published>2018-09-03T09:10:08.000Z</published>
<updated>2018-09-03T14:25:38.540Z</updated>
<content type="html"><![CDATA[<p>HTTP协议是明文形式传输的,传输过程不安全,易被拦截、监听、篡改, HTTPS的诞生正是为了解决HTTP协议不安全的问题。</p><h2 id="什么是HTTPS"><a href="#什么是HTTPS" class="headerlink" title="什么是HTTPS"></a>什么是HTTPS</h2><p>HTTPS协议=HTTP协议+TLS/SSL协议,也就是HTTPS协议是在HTTP协议的基础上加了一层TLS/SSL协议进行数据的加密解密。这样HTTPS协议在网络上传输的数据是加密的密文,拦截后如果没有秘钥进行解密的话拿到的也是一堆乱码。</p><h2 id="几个概念简单理解"><a href="#几个概念简单理解" class="headerlink" title="几个概念简单理解"></a>几个概念简单理解</h2><ol><li>对称加密:用同一个秘钥进行加密解密的方法。</li><li>非对称加密:加密和解密使用不用的秘钥,公钥和私钥。公钥和私钥是一对,使用公钥加密则使用对应的私钥可以进行解密,使用私钥加密则使用对应的公钥可以进行解密。</li><li>证书:这里指数字证书,具有权威性,就像企业公司合同上的印章一样,代表这个是企业授权的合同,包含了由某个受信任组织担保的用户或公司的相关信息。</li><li>CA:Certificate Authority,第三方证书颁发机构。</li><li>TLS:传输层安全(Transport Layer Security,TLS),SSL 和 TLS 非常类似,一般统称为TLS/SSL。</li></ol><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1535966287/3765534683-59ed8581c94b2_articlex.png" alt="数字证书"></p><h2 id="会话秘钥"><a href="#会话秘钥" class="headerlink" title="会话秘钥"></a>会话秘钥</h2><p>非对称加密的计算很慢,实际情况下混合使用了对称加密和非对称加密技术。比较常见的做法是在两节点间通过便捷的公开密钥加密技术建立起安全通信, 然后再用那条安全的通道产生并发送临时的随机对称密钥,通过更快的对称加密技术对其余的数据进行加密。SSH和HTTPS都是这样的。</p><h2 id="数字签名"><a href="#数字签名" class="headerlink" title="数字签名"></a>数字签名</h2><p>非对称加密除了可以用于加密解密外,还可以对报文进行签名(sign),以说明是谁编写的报文,同时证明报文没有被篡改过。这种技术被称为数字签名(digital signing)。</p><h2 id="通信过程"><a href="#通信过程" class="headerlink" title="通信过程"></a>通信过程</h2><ol><li>客户端:向服务端发送一个通信请求,包括随机数PK1、支持的加密协议版本、加密算法、压缩算法等加密套件;</li><li>服务端:发送随机数PK2,确认使用的加密协议版本、加密算法、压缩算法等,以及证书;</li><li>客户端:校验服务端的证书是否合法(包括对域名、有效期、证书颁发机构等),使用证书的公钥加密随机数PK3、加密声明、发送内容的摘要信息,验证服务器身份后,生成一个对称加密算法和对称秘钥;秘钥使用公钥加密发送给服务端;</li><li>服务端:使用私钥解密后,拿到对称秘钥和对称加密算法;</li><li>通信:建立安全通信后,使用协商的对称加密算法及其对应的秘钥进行加密通信。</li></ol><p><img src="https://res.cloudinary.com/diybk7yr1/image/upload/v1535966287/350869942-57c53781ada55_articlex.png" alt="通信过程"></p>]]></content>
<summary type="html">
<p>HTTP协议是明文形式传输的,传输过程不安全,易被拦截、监听、篡改, HTTPS的诞生正是为了解决HTTP协议不安全的问题。</p>
<h2 id="什么是HTTPS"><a href="#什么是HTTPS" class="headerlink" title="什么是HTT
</summary>
<category term="https" scheme="https://scoolor.github.io/tags/https/"/>
<category term="http" scheme="https://scoolor.github.io/tags/http/"/>
</entry>
<entry>
<title>Linux进程组与会话</title>
<link href="https://scoolor.github.io/2018/08/27/linux-session/"/>
<id>https://scoolor.github.io/2018/08/27/linux-session/</id>
<published>2018-08-27T15:16:08.000Z</published>
<updated>2018-08-27T16:21:42.470Z</updated>
<content type="html"><![CDATA[<p>Linux的进程之间有一定的关系,多个进程可以组成进程组,多个进程组又可以构成会话。由于概念比较抽象,这里简单总结一下。</p><h2 id="进程组(process-group)"><a href="#进程组(process-group)" class="headerlink" title="进程组(process group)"></a>进程组(process group)</h2><p>每个进程都属于一个进程组,每个进程组包含一个或多个进程。进程组有一个进程领导进程组(process group leader),领导进程的PID成为进程组的ID(process group ID,PGID),以识别进程组。<br>程序创建了一个进程,该进程又创建了子进程,于是父进程和子进程构成了一个进程组,进程组的组长为父进程。<br>引入的原因:用于控制向多个进程进行信号的分发,发给一个进程组是信号会发生给进程组中每一个进程</p><h2 id="作业(job)"><a href="#作业(job)" class="headerlink" title="作业(job)"></a>作业(job)</h2><p>作业(job)是shell的内部概念。通常shell中的每个作业对应于内核中的一个进程组。所有作业都是进程组,而不是左右的进程组都是作业。</p><h2 id="会话(session)"><a href="#会话(session)" class="headerlink" title="会话(session)"></a>会话(session)</h2><p>通常,会话主要是针对一个终端建立的。一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。<br>当我们打开多个终端窗口时,实际上就创建了多个终端会话。每个会话都会有自己的前台工作和后台工作。这样,我们就为进程增加了管理和运行的层次。在没有图形化界面的时代,会话允许用户通过shell进行多层次的进程发起和管理。<br>多个进程组可以构成一个会话(session),会话由其中一个进程建立,该进程叫做会话的领导进程(session leader),该领导进程的PID成为识别会话的SID(session ID),会话中的每个进程组成为一个工作(job)。<br>会话的意义在于将多个工作囊括在一个终端,并取其中的一个工作作为前台,来直接接收该终端的输入输出以及终端信号。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="https://www.quora.com/What-is-the-difference-between-jobs-and-processes-on-Unix" target="_blank" rel="noopener">https://www.quora.com/What-is-the-difference-between-jobs-and-processes-on-Unix</a></li><li><a href="https://unix.stackexchange.com/questions/9082/difference-between-process-group-and-job" target="_blank" rel="noopener">https://unix.stackexchange.com/questions/9082/difference-between-process-group-and-job</a></li><li><a href="https://www.jianshu.com/p/f64cd61d196c" target="_blank" rel="noopener">https://www.jianshu.com/p/f64cd61d196c</a></li></ol>]]></content>
<summary type="html">
<p>Linux的进程之间有一定的关系,多个进程可以组成进程组,多个进程组又可以构成会话。由于概念比较抽象,这里简单总结一下。</p>
<h2 id="进程组(process-group)"><a href="#进程组(process-group)" class="headerl
</summary>
</entry>
<entry>
<title>Linux重定向</title>
<link href="https://scoolor.github.io/2018/08/16/linux-redirect/"/>
<id>https://scoolor.github.io/2018/08/16/linux-redirect/</id>
<published>2018-08-16T14:09:19.000Z</published>
<updated>2018-08-17T01:06:53.730Z</updated>
<content type="html"><![CDATA[<p>了解linux重定向之前需要先简单介绍一下文件描述符(fd)。</p><h2 id="linux文件描述符:"><a href="#linux文件描述符:" class="headerlink" title="linux文件描述符:"></a>linux文件描述符:</h2><p>文件描述符是一个非负整数,是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开或者创建一个新文件时,内核向进程返回一个文件描述符。<br>一般,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2;文件描述符的有效范围是 0 到 OPEN_MAX。</p><p>linux shell下常用输入输出操作符是:</p><ol><li>标准输入(stdin) :代码为 0 ,使用 < 或 << ; /dev/stdin -> /proc/self/fd/0 0代表:/dev/stdin </li><li>标准输出(stdout):代码为 1 ,使用 > 或 >> ; /dev/stdout -> /proc/self/fd/1 1代表:/dev/stdout</li><li>标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ; /dev/stderr -> /proc/self/fd/2 2代表:/dev/stderr</li></ol><h2 id="输出重定向"><a href="#输出重定向" class="headerlink" title="输出重定向"></a>输出重定向</h2><p>格式:</p><p>command-line1 [1-n] > file或文件操作符或设备</p><p>上面命令意思是:将一条命令执行结果(标准输出,或者错误输出,本来都要打印到屏幕上面的) 重定向其它输出设备(文件,打开文件操作符,或打印机等等)1,2分别是标准输出,错误输出。</p><h2 id="输入重定向"><a href="#输入重定向" class="headerlink" title="输入重定向"></a>输入重定向</h2><p>格式:</p><p>command-line [n] <file或文件描述符&设备</p><p>将然有,命令默认从键盘获得的输入,改成从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定。将由它进行输入。</p><h2 id="常用解释"><a href="#常用解释" class="headerlink" title="常用解释"></a>常用解释</h2><ul><li><code>></code> 表示定向输出到文件,覆盖原有内容;</li><li><code>>></code> 表示定向追加到目标文件,追加到末尾;</li><li><code><</code> 表示导入;</li><li><code>1></code> 表示输出重定向,1可以省略;</li><li><code>2></code> 表示标准错误(stderr)输出重定向;</li><li><code>2>&-</code> 表示将错误输出关闭,&-表示关闭与它绑定的描述符;</li><li><code>1>&-</code> 表示关闭标准输出;</li><li><code>2> /dev/null</code> 表示错误重定向到黑洞,linux 中/dev/null表示黑洞设备,吃掉一切;</li><li><code>>/dev/null 2>&1</code> 将错误输出2绑定给正确输出1,然后将 正确输出 发送给 /dev/null设备</li></ul>]]></content>
<summary type="html">
<p>了解linux重定向之前需要先简单介绍一下文件描述符(fd)。</p>
<h2 id="linux文件描述符:"><a href="#linux文件描述符:" class="headerlink" title="linux文件描述符:"></a>linux文件描述符:</h
</summary>
</entry>
<entry>
<title>使用Certbot开启网站HTTPS</title>
<link href="https://scoolor.github.io/2018/04/18/letsencrypt/"/>
<id>https://scoolor.github.io/2018/04/18/letsencrypt/</id>
<published>2018-04-18T13:25:25.000Z</published>
<updated>2020-02-17T06:46:43.191Z</updated>
<content type="html"><![CDATA[<p>Let’s Encrypt 是一个免费开源的SSL项目,由Mozilla、Cisco、Akamai、IdenTrust、EFF等组织人员发起。在一定程度上Let’s Encrypt推进了国内HTTPS的进程。<br>CertBot 是基于Let’s Encrypt 的简化部署解决方案。另外<a href="https://github.com/Neilpang/acme.sh" target="_blank" rel="noopener">acme</a>也是也不不错的解决方案。<br>下面简单介绍一下使用Certbot部署Let’s Encrypt。</p><h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><p>debian 8 X64<br>nginx</p><p>本文以nginx为例介绍。</p><h1 id="安装Certbot客户端"><a href="#安装Certbot客户端" class="headerlink" title="安装Certbot客户端"></a>安装Certbot客户端</h1><p>Certbot官网:<a href="https://certbot.eff.org/" target="_blank" rel="noopener">https://certbot.eff.org/</a></p><p>debian 8 的默认仓库是没有Certbot的,需要依赖第三方仓库Jessie backports;执行以下命令安装仓库;</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">echo 'deb http://ftp.debian.org/debian jessie-backports main'\</span><br><span class="line">| sudo tee /etc/apt/sources.list.d/backports.list</span><br></pre></td></tr></table></figure><p>执行完后,更新apt包管理工具<br><code>sudo apt-get update</code><br>接下来就可以安装certbot了,执行以下命令<br><code>sudo apt-get install certbot</code> </p><h1 id="获取SSL证书"><a href="#获取SSL证书" class="headerlink" title="获取SSL证书"></a>获取SSL证书</h1><p>let’S Encrypt 支持两种获取证书的方式,Webroot和Standalone,Standalone需要80或443端口没有占用,往往需要暂停nginx服务,所以我们一般使用Webroot方式。<br>首先需要配置一个nginx服务,添加以下配置,重启nginx:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">location ~ /.well-known {</span><br><span class="line"> allow all;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然后执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo certbot certonly -a webroot \</span><br><span class="line">--webroot-path=/var/www/html -d example.com -d www.example.com</span><br></pre></td></tr></table></figure><p>根据提示填写即可。<br>在<code>/etc/letsencrypt/live/</code>目录下就已经生成了你的证书文件。<br>为了进一步提高安全性,需要dhparam.pem文件,生成命令如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048</span><br></pre></td></tr></table></figure><h1 id="配置Nginx"><a href="#配置Nginx" class="headerlink" title="配置Nginx"></a>配置Nginx</h1><p>SSL部分nginx 配置如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;</span><br><span class="line">ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;</span><br><span class="line">ssl_dhparam /etc/ssl/certs/dhparam.pem;</span><br><span class="line"></span><br><span class="line">ssl_session_cache shared:SSL:1m;</span><br><span class="line">ssl_session_timeout 10m;</span><br><span class="line">ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</span><br></pre></td></tr></table></figure><p>80端口配置自动Https</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">return 301 https://$server_name$request_uri;</span><br></pre></td></tr></table></figure><p>最后,测试证书更新:<code>certbot renew --dry-run</code><br>如果没有返回错误信息,则说明配置正常,可以配置自动更新了。</p><p>配置自动更新:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">30 2 * * * /usr/bin/certbot renew --noninteractive \</span><br><span class="line">--renew-hook "/bin/systemctl reload nginx" >> /var/log/le-renew.log</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>Let’s Encrypt 是一个免费开源的SSL项目,由Mozilla、Cisco、Akamai、IdenTrust、EFF等组织人员发起。在一定程度上Let’s Encrypt推进了国内HTTPS的进程。<br>CertBot 是基于Let’s Encrypt 的简化部
</summary>
<category term="Linux" scheme="https://scoolor.github.io/tags/Linux/"/>
<category term="Nginx" scheme="https://scoolor.github.io/tags/Nginx/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="https://scoolor.github.io/2018/04/17/hello-world/"/>
<id>https://scoolor.github.io/2018/04/17/hello-world/</id>
<published>2018-04-17T14:56:28.000Z</published>
<updated>2018-04-17T14:56:28.000Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
<summary type="html">
<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.
</summary>
</entry>
</feed>