#513 iptables (1): 基础知识

2021-04-03

iptables 的历史变更,发展趋势,和其他技术的关联我也曾花了不少时间去了解,可以说还是很不全面,就不献丑了(或者以后再来说说)。

这里就单单讲一下 iptables。

基本思想

在网络数据传输过程中有几个关键点埋上钩子,每个钩子上绑定了一个规则链(CHAIN)。
我们在这些链上注册一些处理规则(RULE),也就是 条件操作
网络包走到埋点的地方时,内核会逐个规则检查,如果符合条件就会执行预定操作。

此外:

  1. 这些处理规则按照不同类型,分成了五类,存在五张不同的表中。
  2. 每个规则链可以设置一个预定的操作(文档中称之为:策略 Policy)。

五个点

  • PREROUTING 路由:内核收到网络包之后,判断该包是否是自己的,应该给哪个程序
  • INPUT 用户程序收到包之前(内核判断是自己的包之后,传输到用户程序)
  • OUTPUT 程序往外发包
  • FORWARD 这个包不是自己的,然后需要中转出去
  • POSTROUTING 路由:系统判断该包应该怎么发出

PS:可以自定义新的链,然后再别的链中引用。我所处理的任务都没有到需要创建新链的地步,所以没有接触过。

五张表

应该说是五个功能。

  • filter 过滤,即判断这个包。默认
  • nat 地址转换
  • mangle 数据包修改,日常网络管理应该不会用到
  • raw 数据包修改(在内核处理之前)
  • security unknown

操作类型

  • ACCEPT 放行
  • DROP 拦截
  • REJECT 拦截,但是告知对方
  • MARK 加标记

NAT

  • SNAT 源地址转换
  • DNAT 目的地址转换
  • REDIRECT 端口转换

参考资料与拓展阅读

#512 Golang: possible resource leak,'defer' is called in the 'for' loop

2021-04-01

类似代码:

for _, f := range files {
    fp, err := os.Open(f)
    if err != nil {
        panic(err)
    }
    defer fp.Close()
    // do something
}

Goland 提示:possible resource leak,'defer' is called in the 'for' loop

defer 是在最后函数退出时执行,但是变量已经经过循环覆盖,可能会导致内存泄漏。
似乎 Golang 的 defer 还是不够聪明。

换种写法:

for _, f := range files {
    func () {
        fp, err := os.Open(f)
        if err != nil {
            panic(err)
        }
        defer fp.Close()
        // do something
    }()
}

#511 Golang ORM 框架

2021-03-30
  • GORM
  • ent
  • Xorm 转到Gitea
  • Bun
  • Reform
  • GoRose

GitHub 搜索结果

  1. go-gorm/gorm shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    The fantastic ORM library for Golang, aims to be developer friendly
  2. ent/ent shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    An entity framework for Go
  3. geektutu/7days-golang shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    7 days golang programs from scratch (web framework Gee, distributed cache GeeCache, object relational mapping ORM framework GeeORM, rpc framework GeeRPC etc) 7 天用 Go 动手写/从零实现系列
  4. gogf/gf shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    GoFrame is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
  5. sqlc-dev/sqlc shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Generate type-safe code from SQL
  6. go-xorm/xorm shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle, Moved to https://gitea.com/xorm/xorm
  7. volatiletech/sqlboiler shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Generate a Go ORM tailored to your database schema.
  8. go-pg/pg shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Golang ORM with focus on PostgreSQL features and performance
  9. go-gorp/gorp shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Go Relational Persistence - an ORM-ish library for Go
  10. xo/xo shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Command line tool to generate idiomatic Go code for SQL databases supporting PostgreSQL, MySQL, SQLite, Oracle, and Microsoft SQL Server
  11. upper/db shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Data access layer for PostgreSQL, CockroachDB, MySQL, SQLite and MongoDB with ORM-like features.
  12. uptrace/bun shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    SQL-first Golang ORM
  13. xxjwxc/gormt shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    database to golang struct
  14. steebchen/prisma-client-go shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    Prisma Client Go is an auto-generated and fully type-safe database client
  15. xormplus/xorm shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    xorm 是一个简单而强大的 Go 语言 ORM 库,通过它可以使数据库操作非常简便。本库是基于原版 xorm 的定制增强版本,为 xorm 提供类似 ibatis 的配置文件及动态 SQL 支持,支持 AcitveRecord 操作
  16. go-reform/reform shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    A better ORM for Go, based on non-empty interfaces and code generation.
  17. gobuffalo/pop shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    A Tasty Treat For All Your Database Needs
  18. bobohume/gonet shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    go 分布式服务器,基于内存 mmo
  19. unionj-cloud/go-doudou shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    go-doudou(doudou pronounce /dəudəu/)is OpenAPI 3.0 (for REST) spec and Protobuf v3 (for grpc) based lightweight microservice framework. It supports monolith service application as well.
  20. gohouse/gorose shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    GoRose(go orm), a mini database ORM for golang, which inspired by the famous php framwork laravle's eloquent. It will be friendly for php developer and python or ruby developer. Currently provides six major database drivers: mysql,sqlite3,postgres,oracle,mssql, Clickhouse.
  21. huandu/go-sqlbuilder shields.io:github/stars shields.io:github/languages/code-size shields.io:github/commit-activity/w shields.io:github/license
    A flexible and powerful SQL string builder library plus a zero-config ORM.

#510 Golang 入门项目 httpbin 总结

2021-03-29

httpbin 是我练手的一个非常简单的小项目,功能就是:
1. HTTP POST 请求 (POST /) 提交一个字符串,服务器返回一个 ID。
1. HTTP GET 请求 (GET /xxxx),返回 ID 对应的字符串。

#509 网卡名称的变迁(ethX -> enpXsY)

2021-03-15

早几年前,Linux 系统的网卡名称都是 eth0、wlan0,后来都变了个风格,就拿我的电脑举例:enp7s0, wlp6s0。
这到底是是什么原因呢?
最近突然好奇,去查了资料才知道为什么。
在 Fedora 的技术资料中找到,这个和 Systemd 有关,然后又在 freedesktop 官网 Systemd 的手册中找到了详细的说明。
现在的命名方案有好长一段,估计要看个半个小时(如果感兴趣可以仔细阅读一下),解开我的疑问却不需要那么复杂。

#506 谷歌身份认证器

2021-03-08

基础概念

身份验证器

Authenticator

密码就算是身份验证器。
加密密钥,比如 SSH 的公钥私钥(密钥对)

动态密码

One-time Password, 缩写: OTP, 又叫做一次性密码

我们常用的的短信验证码就是一种非常方便快捷的动态密码形式。
早些年一些网络服务,比如谷歌、网易通行证等,可能会提供一个动态口令表,包含十几个密码,可以保存为图片,或者纯文本,上面的密码可以逐个使用,每个密码只能用一次。

  • RFC4226 HOTP: An HMAC-Based One-Time Password Algorithm
  • RFC6238 TOTP: Time-Based One-Time Password Algorithm

HOTP 基于 HMAC 算法

简单来说就是根据密钥和计数器来生成一个一次性密码。
除了记住密钥之外,你还要记住这是第几次使用。

  • HOTP value = HOTP(K, C) mod 10d
  • HOTP(K, C) = truncate(HMACH(K, C))
  • truncate(MAC) = extract31(MAC, MAC[(19 × 8) + 4:(19 × 8) + 7] × 8)
  • MAC[(19 × 8) + 4:(19 × 8) + 7] × 8
    取第十九字节的后四位(小端序), 转成一个有符号整型数(小端序),作为截取 MAC 的位置
  • extract31(MAC, i) = MAC[i × 8 + 1:i × 8 + (4 × 8) − 1]
  • MAC[i × 8 + 1:i × 8 + (4 × 8) − 1]
    从上一步得到的位置处,取四个字节,去掉符号位(小端序)

TOTP 基于时间

  1. 协商起始时间 T0 和时间间隔 TX
  2. 双方分别计算时间计数器 CT
  3. TOTP value(K) = HOTP value(K, CT)

多重要素验证

Multi-factor authentication, 缩写: MFA
Two-factor authentication, 缩写: 2FA

谷歌身份验证器

Google 身份验证器是一款 TOTP 与 HOTP 的两步验证软件令牌,此软件用于 Google 的认证服务。此项服务所使用的算法已列于 RFC 6238 和 RFC 4226 中。
Google 身份验证器给予用户一个六位到八位的一次性密码用于进行登录 Google 或其他站点时的附加验证。其同样可以给第三方应用生成口令,例如密码管理员或网络硬盘。先前版本的 Google 身份验证器开放源代码,但之后的版本以专有软件的形式公开。

谷歌验证器基于 TOTP,但是更进一步简化,以约定代替了协商过程。

  1. T0 为 Unix 时间
  2. TX 为 30 秒
  3. 哈希算法为 sha1

此外:

虽然不是很大的创新,而且这个软件验证器实现很简单,但是免费、开放(不需要做任何谷歌服务绑定),加上谷歌的强大影响力,这个软件验证器被很多系统采用。
最后,其他提供动态口令的应用都需要来兼容谷歌身份验证器。

PS: RedHat 开发并维护了开源的 FreeOTP 分支项目。

PS: 微软也有一个 Microsoft Authenticator,阿里云 APP 中有一个 虚拟MFA 功能,都是一个意思。
微软家的为自己提供 8 位密码,别人家的就 6 位,区别对待(虽然感觉好像也并没有什么影响)
阿里云 MFA 是需要手机 APP 登录进去之后才能使用的。

Just4Fun

import base64
import hashlib
import hmac
import time

DEFAULT_INTERVAL = 30  # Google Authenticator: 30 秒
DEFAULT_HASH = hashlib.sha1


def get_hotp_token(secret: str, counter: int, hash_algorithm=DEFAULT_HASH, length=6):
    padding_len = 8 - len(secret) % 8
    if padding_len != 8:
        assert 1 <= padding_len <= 7
        secret += '=' * padding_len
    key = base64.b32decode(secret, True)
    message = (counter & 0xffffffffffffffff).to_bytes(8, 'big')
    mac = hmac.new(key, message, hash_algorithm).digest()
    loc = mac[-1] & 0x0F
    token = (int.from_bytes(mac[loc:loc+4], 'big') & 0x7fffffff) % (10 ** length)
    return token


def get_totp_token(secret, interval=DEFAULT_INTERVAL):
    time_counter = int(time.time()) // interval
    return get_hotp_token(secret, time_counter)


if __name__ == '__main__':
    print('%06d' % get_totp_token(sys.argv[1]))

参考资料与拓展阅读

#505 Windows 命令行操作

2021-03-07

cmd

  • 大小写不敏感
  • 参数通常是 / 开头,而不像 Unix 下是 -
  • 帮助: -help, /?
  • | 管道、> 输出重定向、>> 输出重定向(追加)、< 输入重定向、<< EOF heredoc、<<< CONTENT 输入重定向(字符串)作用和 Linux 相同
  • Ctrl + C 退出执行
help
help | more
dir C:\Windows\System32\*.exe
dir C:\Windows\System32\*.msc

export
echo
cls         # 类似 clear

tasklist
taskkill

cd
mkdir / md
del         # 类似 rm
del /q anydir
rd          # 删除目录(非空目录不可删除)
dir         # 类似 ls
tree
find
findstr     # 类似 grep

ping
ipconfig
netstat
tracert
route
dig
nslookup

shutdown -s -t 300 # 定时关机

explorer # 文件浏览器
notepad  # 记事本
taskmgr  # 命令管理器
regedit  # 注册表编辑器

services.msc # 服务

注册表

Registry, 港澳台地区称之为登录档。就是一个树形结构的数据库,存放系统和应用程序的配置信息。

Linux 下各个应用程序,甚至操作系统的各组件都采用不同的配置文件存储在不同的地方,但 Windows 却采用了这种集中式存储。

https://zh.wikipedia.org/zh-hans/注册表

名称 作用
HKEY_CLASSES_ROOT 存储Windows可识别的文件类型的详细列表,以及相关联的程序。
HKEY_CURRENT_USER 存储当前用户设置的信息。
HKEY_LOCAL_MACHINE 包括安装在计算机上的硬件和软件的信息。
HKEY_USERS 包含使用计算机的用户的信息。
HKEY_CURRENT_CONFIG 这个分支包含计算机当前的硬件配置信息。

常见数据结构:

  • REG_SZ 字符串
  • REG_BINARY 二进制
  • REG_DWORD 32 位二进制值,显示为 8 位的十六进制数
  • REG_MULTI_SZ 多字符串,nul 隔开,结尾两个 nul
  • REG_EXPAND_SZ

python 有内置库 winreg 可以用来操作注册表。

import winreg
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
key_name = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
key = winreg.OpenKey(reg, key_name)
for i in range(1024):
    try:
        sub_key_name = winreg.EnumKey(key, i)
        sub_key = winreg.OpenKey(key, sub_key_name)
        value = winreg.QueryValueEx(sub_key, "DisplayName")
        print('%s: %s' % (sub_key_name, value))
    except EnvironmentError:
        break

Services

# 小心 sc 命令中比较另类的等于号后有空格设计
sc create memcached binPath= "c:\memcached.exe -l 0.0.0.0 -m 128 -d" DisplayName= "Memcached" start= auto

PowerShell

虽然使用频率不高,但和 PowerShell 少有的几次接触感觉很好,很强大。其结构化而非文本的数据结构让人印象深刻。

  • 别名
  • 函数
  • cmdlet
  • 命令
get-alias | findstr /I get-alias
gal | findstr ls

man
help
ls   # Get-ChildItem
ps   # Get-Process
ps | select Name, Id
ps | ft -Property Id, ProcessName, Handles, VM, WS, CPU -AutoSize
ps | where { $_.Name -eq "explorer" }
curl # Invoke-WebRequest
rm      # Remove-Item
rmdir   # Remove-Item
ni -ItemType File -Path C:\Users\Administrator\file.txt  # New-Item
cp      # Copy-Item
cp -Path C:\Users\Administrator\file.txt -Destination D:\Temp\

gcm  # Get-Command
shcm # Show-Command

get-volume

工具

GUI

  • process explorer
  • everything
  • HeidiSQL
  • PuTTY
  • WizTree 目录分析

包管理

  • choco (chocolatey)
  • scoop
  • winget

安装包格式

  • MSI 官方出品, Windows Installer
  • NSIS Nullsoft Scriptable Install System, zlib license
  • WiX
  • Inno Setup

#504 使用 Redis 做消息队列

2021-03-06

Redis 作者还分叉了项目,专门搞了一个实验项目 disque 来实现一个消息队列管理工具。

https://github.com/antirez/disque

这不是这篇文章的关注重点。这篇文章是想像一下使用 Redis 做 MQ 的情况(没在生产环境使用过)。

一、为什么使用 MQ

无非就是减少耦合,削峰填谷。

中间引入一个组件做代理,自然耦合解开了。
另外,一个稳定高效的 MQ 可以快速吸收消息,避免生产者的等待,同时消费者可以根据自己的处理速度来运行。就好像水库的作用,就是削峰填谷,损有余而补不足。
PS: MQ 好像还起到了一点 HA 的作用。
PS: 一种设计完善的消息推送方案,比如一个事件多方消费,如果没有消息队列则需要多次调用。

至于可能导致的问题嘛,当然也有,就是多了一个组件引入了新的复杂性。
上面提到的好处都是建立在 MQ 稳定可靠运行的基础之上,自然需要很多新的工作来维护消息队列中间件。
小规模系统就应该怎么简单怎么来,但如果系统足够复杂,多点工作总是难免的。

1.1 RabbitMQ

Erlang 所写(我听说过的唯一一个 Erlang 项目),AMQP 0-9-1 (高级消息队列协议) 的开源实现(Mozilla 公共许可证)。

  • PS: 摩根大通在 2003 年设计的 AMQP,然后和红帽合作使用 C++ 开发了一个 AMQP 开源实现,就是现在的 Apache Qpid。
  • PS: AMQP v1.0 于 2004 年成为 ISO 标准 (ISO/IEC 19464:2014)。
    据说和 0-9-1 有很大差别。

  • 生产者发布消息给指定 Exchange

  • Exchange 根据路由规则 (RoutingKey) 将消息投递给 Queue
  • 消费者订阅指定 Queue

1.2 Kafka

据说性能非常好,而且是倍经考验了,时不时看到有大型项目将其作为基础设施使用。
虽然最近两年 Kafka 很热门,但我没有在生产环境使用过。

二、Redis 实现

基础功能:

  • 生产消息
  • 存储消息
  • 消费消息

拓展功能:

  • 重复消费(多个消费者)
  • 确认机制
  • 持久化
  • 广播(消息直接写入多个队列)

2.1 List

采用 List 构建一个简单的 FIFO 队列:

  • LPUSH
  • RPOP/BRPOP 如果没有消息了,会返回 nil
  • RPOPLPUSH / BRPOPLPUSH 可以在处理完成之后再从备份队列删除,实现类似 ACK 的功能

PS: RPOPLPUSH: 弹出一个元素,并将该元素压入另一个列表。BRPOPLPUSH: 如果源列表没有元素会阻塞。

redicConn.lpush('queue', 'a')

while True:
    msg = redisConn.rpop('queue')
    if msg is None:
        time.sleep(1)
        continue
    do_something(msg)

2.2 SortedSet

有序集合,不支持重复消息(有时可以当做功能)。

用时间戳(或加一定权重)当分数,据此排序。


2.3 Pub/Sub

实现了简单的 Pub/Sub 功能。
虽然没有 RabbitMQ 那些多 API,也不支持那些复杂的功能配置,但是在简单的场景下用用还是不错的。

  1. 消费者订阅指定主题 subscribe foo
  2. 生产者发布消息 publish foo ooxxooxx

有两个不可忽视的问题:

  1. Pub 上来的消息必须实时发往订阅者,如果订阅者不在线,那么消息就丢失了。
  2. 如果消息积压到一定程度,Redis 会强制断开消费者连接,清空消息队列。

2.4 Streams

Redis 5.0 引入的新数据类型。
这个名字可能是来自流式计算。
所有提交上来的消息按顺序串成一个消息链。

非常值得一提的是,Stream 实现的队列允许重复消费、支持 ACK

  • XADD
  • XDEL
  • XRANGE

三、总结

  1. Redis 不保证数据完整性,所以如果是对数据完整性有要求的话,不能使用这个方案。
  2. Redis 不支持消息确认机制(Ack/Nack/Reject),需要自己在应用层面实现,但如果这么做的话,不如干脆用 MQ 算了。
  3. 除了 Pub/Sub 之外,ListSortedSetStreams 都支持消息持久化,但是应用时需要注意避免消息堆积,否则会可能会对内存造成压力。

如何保证消息的完整性呢?

参考资料与拓展阅读