<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>archive</title><link>https://archive-w.netlify.app/devops/network/</link><description>Recent content on archive</description><generator>Hugo</generator><language>zh-CN</language><atom:link href="https://archive-w.netlify.app/devops/network/index.xml" rel="self" type="application/rss+xml"/><item><title/><link>https://archive-w.netlify.app/devops/network/bridge/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/bridge/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introbridge">
 Intro(Bridge)
 &lt;a class="anchor" href="#introbridge">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;li>
&lt;h2 id="reference">
 Reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;/ul></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/dns/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/dns/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introdns">
 Intro(DNS)
 &lt;a class="anchor" href="#introdns">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;li>
&lt;h2 id="reference">
 Reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>


 &lt;a href="https://app.codecrafters.io/courses/dns-server/setup?repo=114885a4-1081-4ed2-b10a-b0fd258cb1b2" rel="noopener" target="_blank">make a DNS server&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://en.wikipedia.org/wiki/Domain_Name_System#DNS_message_format" rel="noopener" target="_blank">https://en.wikipedia.org/wiki/Domain_Name_System#DNS_message_format&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://datatracker.ietf.org/doc/html/rfc1035#section-4.1" rel="noopener" target="_blank">https://datatracker.ietf.org/doc/html/rfc1035#section-4.1&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://github.com/EmilHernvall/dnsguide/blob/b52da3b32b27c81e5c6729ac14fe01fef8b1b593/chapter1.md" rel="noopener" target="_blank">https://github.com/EmilHernvall/dnsguide/blob/b52da3b32b27c81e5c6729ac14fe01fef8b1b593/chapter1.md&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://www.cloudns.net/blog/understanding-dot-and-doh-dns-over-tls-vs-dns-over-https/" rel="noopener" target="_blank">https://www.cloudns.net/blog/understanding-dot-and-doh-dns-over-tls-vs-dns-over-https/&lt;/a>&lt;/li>
&lt;li>&lt;/li>
&lt;li>域名相关&lt;/li>
&lt;li>


 &lt;a href="https://dnsviz.net/d/wtfu.site/dnssec/" rel="noopener" target="_blank">https://dnsviz.net/d/wtfu.site/dnssec/&lt;/a> [DNS visual]&lt;/li>
&lt;li>


 &lt;a href="https://crt.sh/?q=wtfu.site" rel="noopener" target="_blank">https://crt.sh/?q=wtfu.site&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/docker0/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/docker0/</guid><description>&lt;h2 id="bridge网络">
 bridge网络
 &lt;a class="anchor" href="#bridge%e7%bd%91%e7%bb%9c">#&lt;/a>
&lt;/h2>
&lt;p class="warn"> 目前的理解是&lt;br>
&lt;/br> 1. 容器中的eth0接口通过veth pair 连接到docker0 网桥。
&lt;/br> 2. docker0网桥创建的时候会自动生成一个网络接口并附有172.17.0.1的ip，参考
&lt;/br> 3. docker0 与 eth0 之间没有直接的关联，而是通过 ip_forward/ docker-proxy 等技术进行转发的。参考


 &lt;a href="https://medium.com/@diegogabrielschurch/how-docker-network-works-bridge-driver-e4819459cc8a" rel="noopener" target="_blank">文档&lt;/a>， 有以下片段。
&lt;/br>       &lt;code>Looking at the diagram, the interface docker0 has a connection to the eth0 interface, this gives the ability to our containers to send pings to other machines on the internet. But in reality, this connection is made using a Linux firewall named “Iptables”.&lt;/code>&lt;/p>
&lt;ul>
&lt;li>
&lt;h4 id="参考资料-onehttpwebarchiveorgweb20201109220442httpsdeveloperibmcomrecipestutorialsnetworking-your-docker-containers-using-docker0-bridge">
 参考资料 


 &lt;a href="http://web.archive.org/web/20201109220442/https://developer.ibm.com/recipes/tutorials/networking-your-docker-containers-using-docker0-bridge/" rel="noopener" target="_blank">one&lt;/a>
 &lt;a class="anchor" href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99-onehttpwebarchiveorgweb20201109220442httpsdeveloperibmcomrecipestutorialsnetworking-your-docker-containers-using-docker0-bridge">#&lt;/a>
&lt;/h4>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/docker0/docker0-04.png" alt="">&lt;/p>
&lt;/li>
&lt;li>
&lt;h4 id="参考资料-twohttpssuperusercomquestions1560357is-docker0-virtual-bridge-or-virtual-interface">
 参考资料 


 &lt;a href="https://superuser.com/questions/1560357/is-docker0-virtual-bridge-or-virtual-interface" rel="noopener" target="_blank">two&lt;/a>
 &lt;a class="anchor" href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99-twohttpssuperusercomquestions1560357is-docker0-virtual-bridge-or-virtual-interface">#&lt;/a>
&lt;/h4>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/docker0/docker0-05.png" alt="">&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/http/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/http/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introhttp">
 Intro(HTTP)
 &lt;a class="anchor" href="#introhttp">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="分块传输编码">
 分块传输编码
 &lt;a class="anchor" href="#%e5%88%86%e5%9d%97%e4%bc%a0%e8%be%93%e7%bc%96%e7%a0%81">#&lt;/a>
&lt;/h3>
&lt;p class="warn">Response Header 中存在 &lt;code>Transfer-Encoding: chunked&lt;/code>的话，就是分块传输，数据需要按照 


 &lt;a href="https://zh.wikipedia.org/wiki/分块传输编码#格式" rel="noopener" target="_blank">格式&lt;/a> 解码。[


 &lt;a href="https://en.wikipedia.org/wiki/Chunked_transfer_encoding" rel="noopener" target="_blank">参考&lt;/a>]
&lt;br>&lt;br> 应用场景：使用 socket 发送 http/https 请求的时候会返回数据报文，需要自己解析。比如：
&lt;br>1. 模拟


 &lt;a href="https://github.com/12302-bak/idea-test-project/blob/v2.0.0-BAK/_4_springmvc/src/main/java/site/wtfu/framework/utils/TLSTest.java" rel="noopener" target="_blank">&lt;code>vless客户端发送 wss + https&lt;/code>&lt;/a> 请求: 先与vless服务器创建一个通过tls加密的websocket隧道连接。
&lt;br>2. 发送&lt;code>command(ipaddr, port)&lt;/code> + &lt;code>握手消息&lt;/code>到websocket服务器，并与&lt;code>目标服务器&lt;/code>建立连接并且发送Client Hello[一般情况下是这个]，后续让&lt;code>BC库&lt;/code>完成握手。
&lt;br>3. 读取 &lt;strong>tls&lt;/strong>&lt;code>[BC.TlsClientProtocol]&lt;/code>解密后的报文，此时需要注意可能存在分块传输如下图。&lt;/p>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/http/http-response-chunked-encoding-01.png" alt="" width="70%">&lt;/p>
&lt;/li>
&lt;li>
&lt;h3 id="响应头大小写">
 响应头大小写
 &lt;a class="anchor" href="#%e5%93%8d%e5%ba%94%e5%a4%b4%e5%a4%a7%e5%b0%8f%e5%86%99">#&lt;/a>
&lt;/h3>
&lt;p class="warn">(参考


 &lt;a href="https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2" rel="noopener" target="_blank">rfc | 7540&lt;/a>) 在 http2 中，&lt;strong>响应头的 key 必须为小写&lt;/strong>，其他的视为畸形的，但是在 http1.1 中大小写不敏感。
&lt;br>&lt;br>使用 curl 验证即可，一般浏览器应该会自动转化，比如 chrome 即使小写也会转化成首字母大写。
&lt;br>下列命令查看响应头区别：&lt;code>curl -I --http1.1 https://wtfu.site&lt;/code>，&lt;code>curl -I --http2 https://wtfu.site&lt;/code>
&lt;br>&lt;br>&lt;img src="https://archive-w.netlify.app/.images/devops/network/http/http-response-header-01.png" alt="" width="70%">&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;h2 id="reference">
 Reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>


 &lt;a href="https://en.wikipedia.org/wiki/Chunked_transfer_encoding" rel="noopener" target="_blank">https://en.wikipedia.org/wiki/Chunked_transfer_encoding&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://www.runoob.com/http/http-tutorial.html" rel="noopener" target="_blank">https://www.runoob.com/http/http-tutorial.html&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/network-stack/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/network-stack/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="intro网络栈">
 Intro(网络栈)
 &lt;a class="anchor" href="#intro%e7%bd%91%e7%bb%9c%e6%a0%88">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="直接往网卡发送数据">
 直接往网卡发送数据
 &lt;a class="anchor" href="#%e7%9b%b4%e6%8e%a5%e5%be%80%e7%bd%91%e5%8d%a1%e5%8f%91%e9%80%81%e6%95%b0%e6%8d%ae">#&lt;/a>
&lt;/h3>
&lt;p class="warn">通过对网络模型以及 tcp/ip 协议栈的了解，是可以&lt;strong>不通过协议栈处理&lt;/strong>而使用系统调用直接往网卡上面发送数据的。示例如下：（在 linux 上面的实验，macosx 因为限制原因，修改不了 MAC source address，但是 Linux 完全没有问题。）
&lt;br>&lt;br>抓包命令&lt;code>sudo tcpdump -i eth0 arp -w nic.pcap&lt;/code>， 


 
 

 
 
 
 
 
 
 
 
 
 &lt;a href='https://archive-w.netlify.app/.images/devops/network/network-stack/nic.pcap' rel="noopener" class="internal-link" data-src="https://archive-w.netlify.app/.images/devops/network/network-stack/nic.pcap">nic.pcap file download&lt;/a>
&lt;br>&lt;br>&lt;img src="https://archive-w.netlify.app/.images/devops/network/network-stack/network-stack-nic-send-01.png" alt="" width="100%">&lt;/p>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="c" data-line="" data-cc="400px" class="language-c line-numbers" style="max-height: 400px">&lt;code class="language-c">#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;
#include &amp;lt;net/if.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;
#include &amp;lt;sys/socket.h&amp;gt;
#include &amp;lt;linux/if_packet.h&amp;gt;
#include &amp;lt;net/ethernet.h&amp;gt;

int main() {
 int sockfd;
 struct ifreq if_idx;
 struct sockaddr_ll socket_address;
 char sendbuf[1024];
 unsigned char src_mac[6] = {0x00, 0x0c, 0x29, 0x7b, 0x3e, 0x1f}; // 本机 MAC 地址
 unsigned char dst_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 广播 MAC 地址
 unsigned char *data = &amp;quot;Hello Ethernet!&amp;quot;;
 int data_len = strlen(data);

 // 创建 Packet Socket
 if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
 perror(&amp;quot;socket&amp;quot;);
 exit(EXIT_FAILURE);
 }

 // 获取网络接口索引
 memset(&amp;amp;if_idx, 0, sizeof(struct ifreq));
 strncpy(if_idx.ifr_name, &amp;quot;eth0&amp;quot;, IFNAMSIZ - 1);
 if (ioctl(sockfd, SIOCGIFINDEX, &amp;amp;if_idx) &amp;lt; 0) {
 perror(&amp;quot;SIOCGIFINDEX&amp;quot;);
 close(sockfd);
 exit(EXIT_FAILURE);
 }

 // 填充以太网帧头
 struct ethhdr *eh = (struct ethhdr *)sendbuf;
 memcpy(eh-&amp;gt;h_dest, dst_mac, 6); // 设置目标 MAC 地址
 memcpy(eh-&amp;gt;h_source, src_mac, 6); // 设置源 MAC 地址
 eh-&amp;gt;h_proto = htons(ETH_P_ARP); // 设置协议类型（这里假设是 ARP）

 // 填充数据部分
 memcpy(sendbuf + sizeof(struct ethhdr), data, data_len);

 // 设置目标地址
 memset(&amp;amp;socket_address, 0, sizeof(struct sockaddr_ll));
 socket_address.sll_family = AF_PACKET;
 socket_address.sll_protocol = htons(ETH_P_ARP);
 socket_address.sll_ifindex = if_idx.ifr_ifindex;
 socket_address.sll_halen = ETH_ALEN;
 memcpy(socket_address.sll_addr, dst_mac, 6);

 // 发送数据包
 if (sendto(sockfd, sendbuf, sizeof(struct ethhdr) + data_len, 0,
 (struct sockaddr *)&amp;amp;socket_address, sizeof(struct sockaddr_ll)) &amp;lt; 0) {
 perror(&amp;quot;sendto&amp;quot;);
 close(sockfd);
 exit(EXIT_FAILURE);
 }

 printf(&amp;quot;Data sent successfully!\n&amp;quot;);
 close(sockfd);
 return 0;
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="网络堆栈">
 网络堆栈
 &lt;a class="anchor" href="#%e7%bd%91%e7%bb%9c%e5%a0%86%e6%a0%88">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/network-stack/network-stack-01.png" alt="" width="40%">
&lt;img src="https://archive-w.netlify.app/.images/devops/network/network-stack/network-stack-02.png" alt="" width="57%">&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/proxy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/proxy/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introproxy">
 Intro(PROXY)
 &lt;a class="anchor" href="#introproxy">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;li>
&lt;h2 id="reference">
 Reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;/ul></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/socket/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/socket/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introsocket">
 Intro(SOCKET)
 &lt;a class="anchor" href="#introsocket">#&lt;/a>
&lt;/h2>
&lt;p class="warn">socket 是网络架构中程序与操作系统网络协议栈进行交互的接口API。从所处的地位来讲，套接字上联应用进程，下联网络协议栈，是应用程序通过网络协议进行通信的接口。
&lt;br> 


 &lt;a href="https://github.com/torvalds/linux/blob/master/include/linux/net.h#L117" rel="noopener" target="_blank">linux数据结构定义&lt;/a> 、


 &lt;a href="https://gist.github.com/browny/5211329" rel="noopener" target="_blank">C demo&lt;/a>
&lt;br>&lt;br>作为服务端，先创建一个socket，返回fd，然后与地址(ip+port)进行绑定，监听，然后接收
&lt;br>作为客户端，先创建一个socket，返回fd，然后与地址(serv ad)进行连接，发送&lt;/p>
&lt;ul>
&lt;li>
&lt;h3 id="系统调用">
 系统调用
 &lt;a class="anchor" href="#%e7%b3%bb%e7%bb%9f%e8%b0%83%e7%94%a8">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>
&lt;h4 id="socket">
 socket()
 &lt;a class="anchor" href="#socket">#&lt;/a>
&lt;/h4>
&lt;p>原型：&lt;code>int socket(int domain, int type, int protocol);&lt;/code> 例如：&lt;code>socketfd = socket(AF_INET, SOCK_STREAM, 0);&lt;/code> 


 &lt;a href="https://man7.org/linux/man-pages/man2/socket.2.html" rel="noopener" target="_blank">【man2】&lt;/a>
&lt;br>用来创建一个socket，并且返回引用的文件描述符fd。&lt;/p>
&lt;/li>
&lt;li>
&lt;h4 id="bind">
 bind()
 &lt;a class="anchor" href="#bind">#&lt;/a>
&lt;/h4>
&lt;p>原型：&lt;code>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);&lt;/code> 例如：&lt;code>bind(socketfd, (struct sockaddr*)&amp;amp;serv_addr, sizeof(serv_addr));&lt;/code>


 &lt;a href="https://man7.org/linux/man-pages/man2/bind.2.html" rel="noopener" target="_blank">【man2】&lt;/a>
&lt;br>分配一个地址给socket。&lt;/p>
&lt;/li>
&lt;li>
&lt;h4 id="listen">
 listen()
 &lt;a class="anchor" href="#listen">#&lt;/a>
&lt;/h4>
&lt;p>原型：&lt;code>int listen(int sockfd, int backlog);&lt;/code> 例如：&lt;code>listen(listenfd, 10);&lt;/code>


 &lt;a href="https://man7.org/linux/man-pages/man2/listen.2.html" rel="noopener" target="_blank">【man2】&lt;/a>
&lt;br>listen函数将 socket 文件描述符标记为被动 socket,也就是服务端的socket，执行完之后，文件描述符处于监听状态。使用accept获取客户端连接。backlog 定义 socket允许待处理的客户端连接的队列长度。


 &lt;a href="https://blog.isayme.org/posts/issues-47/" rel="noopener" target="_blank">全连接和半连接&lt;/a>会使用到这个值(和内核版本有关)&lt;/p>
&lt;/li>
&lt;li>
&lt;h4 id="connect">
 connect()
 &lt;a class="anchor" href="#connect">#&lt;/a>
&lt;/h4>
&lt;p>原型：&lt;code>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);&lt;/code> 例如：&lt;code>if( connect(sockfd, (struct sockaddr *)&amp;amp;serv_addr, sizeof(serv_addr)) &amp;lt; 0)&lt;/code>


 &lt;a href="https://man7.org/linux/man-pages/man2/connect.2.html" rel="noopener" target="_blank">【man2】&lt;/a>
&lt;br> 客户端应用使用connect命令在本地socket和远程socket上建立连接。TCP只能调用一次进行三次握手，多次会报错。UPD的话可以调用多次改变关联的socket，好像只是注册一下对端地址 


 &lt;a href="https://www.ibm.com/docs/en/zos/2.4.0?topic=functions-connect" rel="noopener" target="_blank">【IBM connect】&lt;/a> 


 &lt;a href="https://liubigbin.github.io/2016/07/11/UDP%E4%B9%8Bconnect/" rel="noopener" target="_blank">【UDP之connect】&lt;/a>&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/ssh/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/ssh/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introssh">
 Intro(SSH)
 &lt;a class="anchor" href="#introssh">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="ssh登录">
 SSH登录
 &lt;a class="anchor" href="#ssh%e7%99%bb%e5%bd%95">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>
&lt;h4 id="准备步骤">
 准备步骤
 &lt;a class="anchor" href="#%e5%87%86%e5%a4%87%e6%ad%a5%e9%aa%a4">#&lt;/a>
&lt;/h4>
&lt;ol>
&lt;li>生成公私匙: &lt;code>ssh-keygen -t rsa -b 4096 -C 12302@example.com&lt;/code>&lt;/li>
&lt;li>复制公匙到主机:&lt;code>cat ~/.ssh/id_virmach_ras.pub | ssh root@107.174.101.187 &amp;quot;mkdir -p ~/.ssh &amp;amp;&amp;amp; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys&amp;quot;&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/ssh/ssh-keygen-01.png" alt="" width="65%">&lt;/p>
&lt;ul>
&lt;li>
&lt;h5 id="ssh-copy-id使用">
 ssh-copy-id使用
 &lt;a class="anchor" href="#ssh-copy-id%e4%bd%bf%e7%94%a8">#&lt;/a>
&lt;/h5>
&lt;p class="warn">&lt;strong>(ssh-copy-id)&lt;/strong> 是一个可执行的脚本文件，可以把本地的&lt;code>ssh公钥文件&lt;/code>安装到远程主机对应的账户下。也就是将你的公共密钥填充到一个远程机器上的&lt;code>authorized_keys&lt;/code>文件中。如果远程机器上存在&lt;code>authorizedkeys&lt;/code>文件，且&lt;code>authorizedkeys&lt;/code>有内容，则&lt;code>ssh-copy-id&lt;/code> 可以将待传公钥 &lt;em>追加&lt;/em> 到&lt;code>authorizedkeys&lt;/code>文件里。它也能够改变远程用户名的权限，如&lt;code>~/.ssh&lt;/code>和&lt;code>~/.ssh/authorized_keys&lt;/code>删除其写的权限，所以一般&lt;code>/.ssh&lt;/code>给予&lt;code>700&lt;/code>，&lt;code>/.ssh/authorized_keys&lt;/code>给予&lt;code>600&lt;/code>权限。
&lt;br>&lt;br>查看帮助：&lt;code>ssh-copy-id -h&lt;/code>
&lt;br>复制命令：&lt;code>ssh-copy-id [-i [identity_file]] [user@]machine&lt;/code>&lt;/p>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/ssh/ssh-copy-id-01.png" alt="" width="100%">&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;h4 id="登录原理">
 登录原理
 &lt;a class="anchor" href="#%e7%99%bb%e5%bd%95%e5%8e%9f%e7%90%86">#&lt;/a>
&lt;/h4>
&lt;div class="alert flat warning">&lt;p class="title">&lt;span class="icon icon-warning">&lt;/span> Warning &lt;/p>&lt;p> 1). 发送登录请求到远程主机，identity文件中包含一些信息。
&lt;br>2). 远程服务器利用这个账户下的公匙随机生成字符串然后发送给对方。
&lt;br>3). 对方利用私匙将字符串解密后发送给远程服务器。
&lt;br>4). 远程服务器验证通过后，准许对方登录。&lt;/p>
&lt;/p>&lt;/div>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;h3 id="ssh隧道">
 SSH隧道
 &lt;a class="anchor" href="#ssh%e9%9a%a7%e9%81%93">#&lt;/a>
&lt;/h3>
&lt;p class="warn">SSH 除了登录服务器，还有一大用途，就是作为加密通信的中介，充当两台服务器之间的通信加密跳板，使得原本不加密的通信变成加密通信。这个功能称为端口转发（port forwarding），又称 SSH 隧道（tunnel）。
&lt;br>&lt;br>端口转发有两个主要作用：
&lt;br>（1）将不加密的数据放在 SSH 安全连接里面传输，使得原本不安全的网络服务增加了安全性，比如通过端口转发访问 Telnet、FTP 等明文服务，数据传输就都会加密。
&lt;br>（2）作为数据通信的加密跳板，绕过网络防火墙。
&lt;br>端口转发有三种使用方法：&lt;code>动态转发&lt;/code>，&lt;code>本地转发&lt;/code>，&lt;code>远程转发&lt;/code>。下面逐一介绍。&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/tcp/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/tcp/</guid><description>&lt;h2 id="tcp-flag">
 tcp flag
 &lt;a class="anchor" href="#tcp-flag">#&lt;/a>
&lt;/h2>
&lt;h3 id="图例">
 图例
 &lt;a class="anchor" href="#%e5%9b%be%e4%be%8b">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>
&lt;p class="warn">IP 报头（最小20Byte,最大 15[1111] * 32 / 8, 可填充 40Byte ）： 首部长度的单位为 4Byte.&lt;/p>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/tcp/tcp-flag-01.png" alt="">&lt;/p>
&lt;/li>
&lt;li>
&lt;p class="warn">TCP 报头(20Byte)&lt;/p>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/tcp/tcp-flag-02.jpeg" alt="">&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="标志位解释">
 标志位解释
 &lt;a class="anchor" href="#%e6%a0%87%e5%bf%97%e4%bd%8d%e8%a7%a3%e9%87%8a">#&lt;/a>
&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;em>&lt;strong>SYN：同步序列编号（Synchronize Sequence Numbers）&lt;/strong>&lt;/em>&lt;/p>
&lt;p class="tip"> 是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时，客户机首先发出一个SYN消息，服务器使用SYN+ACK应答表示接收到了这个消息，最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接，数据才可以在客户机和服务器之间传递。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>&lt;strong>ACK (Acknowledge character）&lt;/strong>&lt;/em>&lt;/p>
&lt;p class="tip">ACK (Acknowledge character）即是确认字符，在数据通信中，接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。在TCP/IP协议中，如果接收方成功的接收到数据，那么会回复一个ACK数据。通常ACK信号有自己固定的格式,长度大小,由接收方回复给发送方。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>&lt;strong>RST&lt;/strong>&lt;/em>&lt;/p>
&lt;p class="tip">产生RST场景或者导致“Connection reset by peer”场景？&lt;/p>
&lt;ul>
&lt;li>当尝试和未开放的服务器端口建立tcp连接时，服务器tcp将会直接向客户端发送reset报文；&lt;/li>
&lt;li>双方之前已经正常建立了通信通道，也可能进行过了交互，当某一方在交互的过程中发生了异常，如崩溃等，异常的一方会向对端发送reset报文，通知对方将连接关闭；&lt;/li>
&lt;li>当收到TCP报文，但是发现该报文不是已建立的TCP连接列表可处理的，则其直接向对端发送reset报文；&lt;/li>
&lt;li>ack报文丢失，并且超出一定的重传次数或时间后，会主动向对端发送reset报文释放该TCP连接；&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h4 id="相关实验">
 相关实验
 &lt;a class="anchor" href="#%e7%9b%b8%e5%85%b3%e5%ae%9e%e9%aa%8c">#&lt;/a>
&lt;/h4>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/tcp/tcp-flag-04.png" alt="" width="70%" title="04"> &lt;img src="https://archive-w.netlify.app/.images/devops/network/tcp/tcp-flag-03.png" alt="" width="29%" title="03">&lt;/p>
&lt;ul>
&lt;li>&lt;em>&lt;strong>猜想&lt;/strong>&lt;/em>
&lt;ol>
&lt;li>
&lt;p>ack值：&lt;/p>
&lt;p class="warn">存在SYN时，ack为对方的seq+1，&lt;/br>
存在PSH时，ack为对方的seq+len,&lt;/p>
&lt;/li>
&lt;li>
&lt;p>seq值：&lt;/p>
&lt;p class="warn">存在ACK时，seq为对方的ack.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h2 id="socket_keepalive理解">
 socket_keepalive理解
 &lt;a class="anchor" href="#socket_keepalive%e7%90%86%e8%a7%a3">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="前言">
 前言
 &lt;a class="anchor" href="#%e5%89%8d%e8%a8%80">#&lt;/a>
&lt;/h3>
&lt;p class="warn">1. net.ipv4.tcp_keepalive_intvl = 75 （发送探测包的周期，前提是当前连接一直没有数据交互，才会以该频率进行发送探测包，如果中途有数据交互，则会重新计时tcp_keepalive_time，到达规定时间没有数据交互，才会重新以该频率发送探测包）
&lt;/br> 2. net.ipv4.tcp_keepalive_probes = 9  （探测失败的重试次数，发送探测包达次数限制对方依旧没有回应，则关闭自己这端的连接）
&lt;/br> 3. net.ipv4.tcp_keepalive_time = 7200 （空闲多长时间，则发送探测包）&lt;/p>
&lt;/li>
&lt;li>
&lt;h3 id="响应结果">
 响应结果
 &lt;a class="anchor" href="#%e5%93%8d%e5%ba%94%e7%bb%93%e6%9e%9c">#&lt;/a>
&lt;/h3>
&lt;p class="warn">1. 正常ack，继续保持连接；
&lt;/br> 2. 对方响应rst信号，双方重新连接。
&lt;/br> 3. 对方无响应。&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/tun-tap/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/tun-tap/</guid><description>&lt;h2 id="tuntap">
 tun/tap
 &lt;a class="anchor" href="#tuntap">#&lt;/a>
&lt;/h2>
&lt;p class="warn">tun/tap 设备是操作系统内核中的虚拟网络设备，是用软件模拟的网络设备，提供与硬件网络设备完全相同的功能。主要用于用户空间和内核空间传递报文。&lt;/p>
&lt;h3 id="tuntap-设备与物理网卡的区别如图所示">
 &lt;strong>tun/tap 设备与物理网卡的区别，如图所示:&lt;/strong>
 &lt;a class="anchor" href="#tuntap-%e8%ae%be%e5%a4%87%e4%b8%8e%e7%89%a9%e7%90%86%e7%bd%91%e5%8d%a1%e7%9a%84%e5%8c%ba%e5%88%ab%e5%a6%82%e5%9b%be%e6%89%80%e7%a4%ba">#&lt;/a>
&lt;/h3>
&lt;ol>
&lt;li>对于硬件网络设备而言，一端连接的是物理网络，一端连接的是网络协议栈。&lt;/li>
&lt;li>对于 tun/tap 设备而言，一端连接的是应用程序（通过 字符设备文件 /net/dev/tun），一端连接的是网络协议栈。
&lt;img src="https://archive-w.netlify.app/.images/devops/network/tun-tap/tun-tap-01.png" alt="">&lt;/li>
&lt;/ol>
&lt;h3 id="工作原理">
 &lt;strong>工作原理&lt;/strong>
 &lt;a class="anchor" href="#%e5%b7%a5%e4%bd%9c%e5%8e%9f%e7%90%86">#&lt;/a>
&lt;/h3>
&lt;blockquote>
&lt;p>从下图可以更直观的看出 tun/tap 设备和物理设备的区别：虽然它们的一端都是连着网络协议栈，但是物理网卡另一端连接的是物理网络，而 tun/tap 设备另一端连接的是一个应用层程序，这样协议栈发送给 tun/tap 的数据包就可以被这个应用程序读取到，此时这个应用程序可以对数据包进行一些自定义的修改(比如封装成 UDP)，然后又通过网络协议栈发送出去——其实这就是目前大多数“代理”的工作原理。(Tun/tap 设备提供的虚拟网卡驱动，从tcp/ip协议栈的角度而言，它与真实网卡驱动并没有区别。)&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/devops/network/tun-tap/tun-tap-02.jpg" alt="">&lt;/p>
&lt;h4 id="工作模式">
 &lt;strong>工作模式&lt;/strong>
 &lt;a class="anchor" href="#%e5%b7%a5%e4%bd%9c%e6%a8%a1%e5%bc%8f">#&lt;/a>
&lt;/h4>
&lt;p class="warn">tun/tap 有两种模式，tun 模式 与 tap 模式。tun 设备与 tap 设备工作方式完全相同，区别在于：&lt;/p>
&lt;ol>
&lt;li>Tun 设备是三层设备，从 /dev/net/tun 字符设备上读取的是 IP 数据包，写入的也只能是 IP 数据包，因此不能进行二层操作，如发送 ARP 请求和以太网广播。&lt;/li>
&lt;li>Tap 设备是二层设备，处理的是二层 MAC 层数据帧，从 /dev/net/tun 字符设备上读取的是 MAC 层数据帧，写入的也只能是 MAC 层数据帧。从这点来看， Tap 虚拟设备和真实的物理网卡的能力更接近，可以与物理网卡做 bridge。&lt;/li>
&lt;/ol>
&lt;p class="tip">&lt;strong>注意事项&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>无论是 tun 还是 tap 设备，都是通过 open/dev/net/tun 这个字符设备文件，通过 ioctl 系统调用在内核创建新的 tun、tap 设备，创建的设备并不会以文件的形式出现在 /dev/ 下，可以在 sys/class/net/ 下看到对应的网络接口 tunx 或者 tapx。&lt;/li>
&lt;li>设备 /dev/net/tun 必须以 read/write 的方式打开。该设备也被称为克隆设备，它是创建任何 tun/tap 虚拟接口的起点。&lt;/li>
&lt;li>open 系统调用执行的时候，VFS 会为这次 open 分配一个独立的内核态 file 结构，也就是说，每次打开执行时，内核为此次打开分配的 file 结构实例不同，代表不同的字符设备。&lt;/li>
&lt;/ul>
&lt;h4 id="应用的数据收发过程">
 &lt;strong>应用的数据收发过程&lt;/strong>
 &lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e7%9a%84%e6%95%b0%e6%8d%ae%e6%94%b6%e5%8f%91%e8%bf%87%e7%a8%8b">#&lt;/a>
&lt;/h4>
&lt;ol>
&lt;li>数据发送：应用进程 A open/dev/net/tun 字符设备，通过 ioctl 调用创建虚拟接口 tunx 或者 tapx, ioctl 调用返回表示对应 tunx 或者 tapx 设备的文件描述符 fd ，应用 A 通过这个文件描述符 fd 写入格式化的数据，数据通过虚拟网卡驱动到达协议栈，对于协议栈来说，这个数据就像从真实网卡接收的一样。&lt;/li>
&lt;li>数据接收：当网络协议栈发送数据到虚拟接口 tunx 或者 tapx 时，应用进程 A 通过上述创建的设备文件描述符 fd，从中读取接口发送的数据，然后进行处理。&lt;/li>
&lt;/ol>
&lt;h3 id="设备创建">
 &lt;strong>设备创建&lt;/strong>
 &lt;a class="anchor" href="#%e8%ae%be%e5%a4%87%e5%88%9b%e5%bb%ba">#&lt;/a>
&lt;/h3>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="shell" data-line="" class="language-shell line-numbers" style="max-height: none">&lt;code class="language-shell"># 创建 tun/tap 设备
ip tuntap add dev tap0 mod tap # 创建 tap
ip tuntap add dev tun0 mod tun # 创建 tun
 
# 删除tun/tap设备
ip tuntap del dev tap0 mod tap # 删除 tap
ip tuntap del dev tun0 mod tun # 删除 tun
 
# 设置 ip 地址，up 设备
ip address add dev tap0 10.0.1.5/24
ip link set dev tap0 up
&lt;/code>&lt;/pre>&lt;/div>
&lt;h3 id="设备驱动">
 &lt;strong>设备驱动&lt;/strong>
 &lt;a class="anchor" href="#%e8%ae%be%e5%a4%87%e9%a9%b1%e5%8a%a8">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Tun/tap 驱动程序中包含两个部分，一部分是字符设备驱动，还有一部分是网卡驱动。&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/devops/network/vmware/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/devops/network/vmware/</guid><description>&lt;h2 id="reference">
 Reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>


 &lt;a href="https://blog.csdn.net/a745233700/article/details/90230490" rel="noopener" target="_blank">https://blog.csdn.net/a745233700/article/details/90230490&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>