January 16, 2023
Golang 中网络请求使用指定网卡
当用户发起一个网络请求时,流量会通过默认的网卡接口流出与流入,但有时需要将流量通过指定的网卡进行流出流入,这时我们可能需要进行一些额外的开发工作,对其实现主要用到了 Dialer.Control 配置项。
type Dialer struct { // If Control is not nil, it is called after creating the network // connection but before actually dialing. // // Network and address parameters passed to Control method are not // necessarily the ones passed to Dial. For example, passing "tcp" to Dial // will cause the Control function to be called with "tcp4" or "tcp6". Control func(network, address string, c syscall.
December 28, 2022
Envoy中的 gRPC限流服务
上一节 我们大概介绍了一下Envoy中有关速率限制(限流)的一些内容,这一节我们看一下对于外部的 gRPC限流服务它又是如何工作和配置的。
在 Envoy 中对服务限流的配置除了可以在 Envoy 本身中实现外,还可以在通过外部服务实现,此时 Envoy 将通过 gRPC 协议调用外部限流服务,官方对此实现有一套现成的解决方案,主要是redis数据库+令牌桶算法实现,可参考官方
本文中的限制器或限流器均是同一个意思。
Envoy 实现限流 此实现是基于令牌桶算法实现,本身比较的简单,比较适合一般的使用场景。
这里是官方提供的一个配置示例
13 http_filters: 14 - name: envoy.filters.http.local_ratelimit 15 typed_config: 16 "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit 17 stat_prefix: http_local_rate_limiter 18 token_bucket: 19 max_tokens: 10000 20 tokens_per_fill: 1000 21 fill_interval: 1s 22 filter_enabled: 23 runtime_key: local_rate_limit_enabled 24 default_value: 25 numerator: 100 26 denominator: HUNDRED 27 filter_enforced: 28 runtime_key: local_rate_limit_enforced 29 default_value: 30 numerator: 100 31 denominator: HUNDRED 32 response_headers_to_add: 33 - append_action: OVERWRITE_IF_EXISTS_OR_ADD 34 header: 35 key: x-local-rate-limit 36 value: 'true' 37 local_rate_limit_per_downstream_connection: false 重点关注配置项 token_bucket ,这里的配置表示当前最多有 10000 个令牌可以被使用,其中令牌在使用的过程中,只要桶中不足10000 个令牌时,则会以每秒再产生 1000 个令牌的速度产生新的令牌并放入令牌桶中,这样就可以实现后期每秒 1000个请求的需求。
December 20, 2022
Envoy 中的速率限制 ratelimit
在 Envoy 架构中 Rate limit service 共支持 global rate limiting 和 local rate limit filter 两种速率限制。推荐使用 https://github.com/envoyproxy/ratelimit 库。
Global rate limiting Envoy 提供了两种全局限速实现
每个连接 或 每个HTTP请求 速率限制检查。 基于配额,具有定期负载报告,允许在多个 Envoy 实例之间公平共享全局速率限制。此实现适用于每秒请求负载较高的大型 Envoy 部署,这些负载可能无法在所有 Envoy 实例之间均匀平衡。 Per connection or per HTTP request rate limiting Envoy 直接与全局 gRPC rate limiting service 集成,配置参考 https://www.envoyproxy.io/docs/envoy/latest/configuration/other_features/rate_limit#config-rate-limit-service。
速率服务可以使用任何 RPC/IDL 协议实现,但Envoy 提供了一个用 Go 编写的参考实现,它使用 Redis 作为后端。速率集成有以下两种特征:
Network 级别过滤器:对应 Per connection ,Envoy 将为安装过滤器的侦听器上的每个 新连接 调用速率限制服务。该配置指定一个特定的域名和描述符设置为速率限制。这具有限制每秒传输侦听器的连接速率的最终效果。配置参考 https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/rate_limit_filter#config-network-filters-rate-limit
HTTP 级别过滤器: 对应 Per HTTP request,Envoy 将为安装过滤器的 Listener 以及路由表指定应调用全局速率限制服务的侦听器上的每个 新请求 调用速率限制服务。对目标上游集群的所有请求以及从原始集群到目标集群的所有请求都可以进行速率限制。配置参考 https://www.
November 30, 2022
shell终端配置
oh-my-zsh 是一款非常不错的shell配置,最近几年一直是重度用户。由于一些原因经常登录一些服务器,这里根据自己的习惯做一个笔记,以后不用每一次都要重新从各个地方找安装脚本了。
安装 zsh 安装zsh 一般系统默认的都是bash,所以我们先安装 zsh。如果不清楚当前使用的哪一类shell的,可通过以下命令查看
$ cat $SHELL /bin/bash 我这里使用的默认shell。根据平台选择相应的安装zsh命令, 我这里是Ubuntu系统。
Linux、Debian平台
sudo apt install -y zsh macOS
brew install zsh Centos/RHE
sudo yum update && sudo yum -y install zsh 确认版本 $ zsh --version zsh 5.8.1 (aarch64-unknown-linux-gnu) 查看 /etc/shell 看是否存在zsh
$ cat /etc/shells /bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /usr/bin/sh /bin/dash /usr/bin/dash /usr/bin/tmux /usr/bin/screen /bin/zsh /usr/bin/zsh 这里有两个 zsh, 其实它们是同一个, 不用管它。
切换默认shell chsh -s $(which zsh) 注销用户,重新登录终端,再看确认是否切换默认shell成功。
node2% echo $SHELL /usr/bin/zsh 现在看到终端提示符发生了变化。
October 31, 2022
在 vmware 里扩容Linux硬盘空间
在mac上创建了一个ubuntu的虚拟机做为k8s远程开发调试机器,但在编译程序的时候发现磁盘空间不足,于是需要对磁盘进行扩容。
下面为整个硬盘扩容过程。
硬盘扩容 首先将虚拟机关机,在 Vmware Fusion 软件上面菜单,点击 Virtual Machine -> Setting 菜单,然后在突出框框里的找到硬盘 Hard Disk ,点击调整硬盘空间大小,然后点击Apply 应用按钮。
磁盘格式化 查看当前磁盘分区信息
sxf@vm:~/workspace$ sudo fdisk -l [sudo] password for sxf: Disk /dev/loop0: 63.29 MiB, 66359296 bytes, 129608 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk /dev/loop1: 63.46 MiB, 66531328 bytes, 129944 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk /dev/loop2: 91.
October 30, 2022
Linux下两种 DNAT 用法的差异
前段时间使用 iptables 的 DNAT 实现一个业务需求的时候,遇到了一些问题这里将其整个过程记录下来。
需求 这里假设开发机地址为 192.168.3.80,要实现的需求是当用户在开发机访问一个IP地址 192.168.3.196时,将请求转发到另一台机器 192.168.3.58,很明显直接使用 DNAT 来实现即可。
问题现象 iptables 命令如下
sudo iptables -t nat -F sudo iptables -t nat -A PREROUTING -d 192.168.3.196 -p tcp --dport 8080 -j DNAT --to-destination 192.168.3.58:8080 sudo iptables -t nat -A POSTROUTING -d 192.168.3.58 -p tcp --dport 8080 -j SNAT --to-source 192.168.3.196:8080 这时在开发机器访问
curl http://192.168.3.196:8080 发现提示错误
curl: (7) Failed to connect to 192.168.3.196 port 8080: Connection refused 奇怪了,竟然不能访问,确认路由规则是写入成功的。网上查找了一些资料好像全是这种写法,只不过用法有怕差异,这时直觉告诉我应该对 DNAT 理解不到位,遗漏了一些重要的知识点。
July 20, 2022
Linux中调试 iptables
环境:
客户端(windows) 192.168.6.21
服务器(Ubuntu): 192.168.6.23
开启iptables调试内核模块 $ modprobe nf_log_ipv4 $ sysctl net.netfilter.nf_log.2 net.netfilter.nf_log.2 = nf_log_ipv4 添加iptables规则 $ iptables -t raw -A PREROUTING -p icmp -j TRACE $ iptables -t raw -A OUTPUT -p icmp -j TRACE 测试规则 客户端执行 ping 命令,
$ ping 192.168.6.23 -n 1 这里使用 -n 参数指定发送的包数量为1,方便我们分析日志
此时在服务器上执行查看日志命令, 日志文件为:/var/log/syslog 或者 /var/log/kern.log 或者 /var/log/messages
$ tail -f /var/log/syslog Jul 20 11:28:40 ubuntu kernel: [ 7606.531051] TRACE: raw:PREROUTING:policy:2 IN=ens37 OUT= MAC=00:0c:29:30:06:44:00:68:eb:c6:60:f2:08:00 SRC=192.
June 10, 2022
https 是如何建立连接的
一、什么是HTTPS、TLS、SSL HTTPS,也称作HTTP over TLS。TLS的前身是SSL,TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。下图描述了在TCP/IP协议栈中TLS(各子协议)和HTTP的关系。
二、HTTP和HTTPS协议的区别 1、HTTPS协议需要到证书颁发机构(Certificate Authority,简称CA)申请证书,一般免费证书很少,需要交费。
2、HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。
3、HTTP和HTTPS使用的是完全不同的连接方式,使用的端口也不一样,前者是80,后者是443。
4、HTTP的连接很简单,是无状态的。
5、HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全。
从上面可看出,HTTPS和HTTP协议相比提供了
· 数据完整性:内容传输经过完整性校验
· 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
· 身份认证:第三方无法伪造服务端(客户端)身份
其中,数据完整性和隐私性由TLS Record Protocol保证,身份认证由TLS Handshaking Protocols实现。
三、证书 1、什么是证书呢?
2、证书中包含什么信息
证书信息:过期时间和序列号
所有者信息:姓名等
所有者公钥
3、为什么服务端要发送证书给客户端
互联网有太多的服务需要使用证书来验证身份,以至于客户端(操作系统或浏览器等)无法内置所有证书,需要通过服务端将证书发送给客户端。
4、客户端为什么要验证接收到的证书
中间人攻击
5、客户端如何验证接收到的证书
为了回答这个问题,需要引入数字签名(Digital Signature)。
将一段文本通过哈希(hash)和私钥加密处理后生成数字签名。
假设消息传递在Bob,Susan和Pat三人之间发生。Susan将消息连同数字签名一起发送给Bob,Bob接收到消息后,可以这样验证接收到的消息就是Susan发送的
当然,这个前提是Bob知道Susan的公钥。更重要的是,和消息本身一样,公钥不能在不安全的网络中直接发送给Bob。
此时就引入了证书颁发机构(Certificate Authority,简称CA),CA数量并不多,Bob客户端内置了所有受信任CA的证书。CA对Susan的公钥(和其他信息)数字签名后生成证书。
Susan将证书发送给Bob后,Bob通过CA证书的公钥验证证书签名。
Bob信任CA,CA信任Susan, 使得 Bob信任Susan,信任链(Chain Of Trust)就是这样形成的。
事实上,Bob客户端内置的是CA的根证书(Root Certificate),HTTPS协议中服务器会发送证书链(Certificate Chain)给客户端。
正式开始HTTPS的内容:
一、HTTPS的基本原理 从上面可知,HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。
HTTPS其实是有两部分组成:HTTP +SSL/ TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的,且看下图。
1. 客户端发起HTTPS请求 这个没什么好说的,就是用户在浏览器里输入一个HTTPS网址,然后连接到server的443端口。
2. 服务端的配置 采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
3. 传送证书 这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
June 10, 2022
实现 Linux 终端录屏转gif动画
在一些开源其中,有些文档使用git动画来介绍的话效果会好很多,所以这里把在Linux终端下如何生成git动画效果整理出来,供大家参考。
安装录屏软件 asciinema Mac
brew install asciinema Ubuntu
sudo apt-add-repository ppa:zanchey/asciinema Debian
sudo apt-get install asciinema Pip安装
sudo pip3 install asciinema 目前此软件不支持 Windows。更多安装教程参考:
用法介绍 ❯ asciinema -h usage: asciinema [-h] [--version] {rec,play,cat,upload,auth} ... Record and share your terminal sessions, the right way. positional arguments: {rec,play,cat,upload,auth} rec Record terminal session play Replay terminal session cat Print full output of terminal session upload Upload locally saved terminal session to asciinema.org auth Manage recordings on asciinema.
May 24, 2022
Linux 中的 Tun/Tap 介绍
TUN/TAP 设备 在计算机中TUN与TAP是操作系统内核中的虚拟网络设备。不同于硬件设备这些虚拟的网络设备全部用软件实现,但提供了与硬件设备完全相同的功能。
我们先了解一下物理设备的工作原理 所有主机物理网卡收到的数据包时,会先将其交给内核的 Network Stack 处理,然后通过 Socket API 通知给用户态的用户程序。
Linux 中 Tun/Tap 驱动程序为应用程序提供了两种交互方式:
虚拟网络接口和字符设备 /dev/net/tun。写入字符设备 /dev/net/tun 的数据会发送到虚拟网络接口中; 发送到虚拟网络接口中的数据也会出现在该字符设备上; 我们再看下 tun 设备的工作原理 用户态应用往字符设备 /dev/tunX 写数据时,写入的数据都会出现在TUN虚拟设备上,当内核发送一个包给 TUN 虚拟设备时,通过读这个字符设备 /dev/tunX 同样可以拿到包的内容。
用户态应用程序写数据到 tun/tap 设备后进入内核态,内核态通过TCP协议复制到用户态,最后数据再次复制到内核态并通过物理网卡转发出去,期间共经历了三次用户态与内核态的复制操作,相比传统的一次复制操作来说,开销还是比较大的,因此性能会有一定的下降,这正是它的缺点。
TAP 设备与 TUN 设备工作方式完全相同,区别在于:
TUN 设备的 /dev/tunX 文件收发的是 IP 层数据包,只能工作在 IP 层,无法与物理网卡做 bridge,但是可以通过三层交换(如 ip_forward)与物理网卡连通。 TAP 设备的 /dev/tapX 文件收发的是 MAC 层数据包,拥有 MAC 层功能,可以与物理网卡做 bridge,支持 MAC 层广播 应用场景 tun/tap 的最主要应用场景就是 vpn。 基实现原理就是用到隧道技术,将无法直接发送的包通先封成允许通过的合法数据包,然后经过隧道的方式传递给对方,对方收到数据包再解包成原始数据包,再继续传递下去,直到接收端收到,然后响应并原路返回。 以下图为例
应用进程(用户态)发起一个请求时,数据包并不是直接通过eth0网卡流出去,而是将请求数据包写入一个 TUN 字符设备,此时字符设备的数据会被发到虚拟网卡上(进入内核态)。根据TUN设置的特点,凡是写到这个设备的数据都可以在设备的另一端被应用程序读出的原理,应用程序客户端VPN(Port:28001)不断的从TUN 设备里将数据包读出来,然后再经过物理的网卡 eth0(IP1) 网卡流出,这一步就是一个普通的应用程序的客户端发起一个请求的过程。 流出的数据包通过 eth0 (IP2)被服务端VPN(Port:38001)接收到,然后再将收到的数据包以同样的方式写入 TUN 设备,此时进入内核态,经过 TCP/IP 协议栈,则再次将数据包经过物理网卡eth0(IP2)出去,经过交换同机或路由器直到最终到达目的主机(目的主机非本机)。 然后目的主机将响应按原来的线路返回给发起请求应用程序。 总结