L B T

记 录 过 去 的 经 验

加密解密相关常用概念

  • Plain Text : 明文,可以被人类或者激情理解的内容
  • Ciphertext : 密文,加密后的内容,一般不能直接被人类或者机器所理解,需要解密
  • Encryption : 将 Plain Text 转换为 Ciphertext 的过程,通常使用一种加密算法(Encrypt Algorithm)
  • Decryption : 解密,将 Ciphertext 转换为 Plain Text 的过程,通常使用和加密算法(Encrypt Algorithm)相对应的解密算法(Decrypt Algorithms)
  • Cipher : 加密和解密过程中算法使用的密码。
  • Block Cipher : 在对数据进行加密之前,需要首先将其分割成块(Block)
  • Stream Cipher : 加密过程中无需将其分割成块(Block)
  • Key : 通常值密钥对(公钥/私钥)

以下是一些较为经典的加密算法

Algorithm Description
AES
Advanced Encryption Standard, also called Rijndael
- Symmetric Cryptography
- Block Cipher 。encrypting data in 128-, 192-, 256-, 512- bit, blocks using a 128-, 192-, 256, or 512-bit key
Blowfish - Symmetric Cryptography
- Block Cipher 。encrypting data in 64-bit blocks using the same 32-bit to 448-bit keys for encrypting/decrypting.
CAST5 - Symmetric Cryptography
- Block Cipher 。 encrypting data in 64-bit blocks using the same up to 128-bit key for encrypting/decrypting.
DES
Data Encryption Standard
已经被认为是不安全的
- Symmetric Cryptography
- Block Cipher 。encrypting data in 64-bit blocks using the same 56-bit key for encrypting/decrypting.
3DES 增强的 DES 加密算法
- Symmetric Cryptography
Data is encrypted up to 48 times with three different 56-bit keys before the encryption process is completed.
IDEA - Symmetric Cryptography
- Block Cipher 。 encrypting data in 64-bit blocks using the same 128-bit key for encrypting/decrypting
RC5 - Symmetric Cryptography
- Block Cipher 。 encrypting data in 32-, 64-``, or 128- bit blocks ,using the same up to 2,048-bit keys for encrypting/decrypting
RC6 - Symmetric Cryptography
Same as RC5, but slightly faster
EI Gamal - Asymmetric Cryptography
Uses two keys derived from a logarithm algorithm
Elliptic Curve Cryptosystems - Asymmetric Cryptography
Uses two keys derived from an algorithm containing two randomly chosen points on an elliptic curve.
RC4
also called ArcFour or ARC4
- Stream Cipher
encrypting data in 64-bit blocks using a variable key size for encrypting/decrypting.
RSA 最流行的非对称加密算法,使用 Public/Private Key 进行加解密
- Asymmetric Cryptography
阅读全文 »

Hash 不是加密(Encryption),不像 加密(Encrypt)-解密(decrypt)对一个对象进行 Hash 操作后,不可能通过 Hash 后的值 dehash 回原来的对象

Hash 算法需要 Collision Free ,即对两个完全不同的输入,经过 Hash 算法后的值也必须 不同

在 Linux 系统中,用户名秘密验证就是使用 Hash 算法。/etc/shadow 中包含的是用户密码(加 Salt) Hash 后的值,而不是用户密码,当用户使用密码登陆系统时,会计算用户密码(加 Salt)的 Hash 值并和 /etc/shadow 中保存的内容进行对比以验证用户密码是否正确。

Hash 在 Linux 系统中,有以下用途:

  • Passwords 验证
  • 校验文件内容
  • 数字签名
  • 病毒签名

Hash 也有以下叫法:

  • Message Digest : 消息摘要,Linux 中常用的命令如 md5sumsha1sumsha224sumsha256sumsha384sumsha512sumshasum 等应用了不同的 Hash 算法
  • Checksum : 校验和
  • Fingerprint : 数字指纹
  • Signature : 签名

Hash 常见用途示例

内容完整性校验

例如网上公开的 ISO 系统镜像,发布者会同时发布镜像的 SHA-256 Hash 算法摘要值,当你下载了此镜像后,可以在本地对其镜像同样的 Hash 计算(如 sha256sum 命令),如果计算出的值和发布者公布的值一致,说明其内容和发布者发布的镜像内容一致(未被篡改)

$ sha256sum Fedora-Workstation-Live-x86_64-30-1.2.iso
a4e2c49368860887f1cc1166b0613232d4d5de6b46f29c9756bc7cfd5e13f39f
Fedora-Workstation-Live-x86_64-30-1.2.iso

Linux 审计系统提供了一种方式来跟踪系统上与安全相关的信息。根据预配置的规则,审计会生成日志条目,来尽可能多地记录系统上所发生的事件的相关信息。对于关键任务环境而言至关重要,可用来确定安全策略的违反者及其所执行的操作。审计不会为您的系统提供额外的安全,而是用于发现系统上使用的安全策略的违规。可以通过其他安全措施(如 SELinux)进一步防止这些违规。 [1]

以下列表总结了审计可以在其日志文件中记录的一些信息:

  • 事件的日期、时间、类型和结果.
  • 主题和对象的敏感度标签。
  • 事件与触发事件的用户身份的关联。
  • 对审计配置的所有修改,以及对访问审计日志文件的尝试。
  • 所有身份验证机制的使用,如 SSH 和 Kerberos 等。
  • 对任何受信任数据库的修改,如 /etc/passwd。
  • 尝试将信息导入系统或从系统导出。
  • 根据用户身份、主题和对象标签以及其他属性包含或排除事件。

使用案例

  • 监视文件访问
    审计可以跟踪文件或目录是否已被访问、修改、执行或者文件的属性是否已改变。例如,这有助于检测对重要文件的访问,并在其中一个文件损坏时提供审计跟踪。
  • 监控系统调用
    可将审计配置为在每次使用特定系统调用时生成日志条目。例如,这可用于通过监控 settimeofdayclock_adjtime 和其他与时间相关的系统调用来跟踪对系统时间的修改。
  • 记录用户运行的命令
    审计可以跟踪文件是否已被执行,因此可以定义一个规则以记录每次特定命令的执行。例如,可以对 /bin 目录中的每个可执行文件定义一个规则。然后,可以按用户 ID 搜索生成的日志条目,以生成每个用户所执行的命令的审计跟踪。
  • 记录系统路径名称的执行
    除了观察在规则调用时将路径转换为 inode 的文件访问之外,审计现在还可以观察路径的执行,即使路径在规则调用中不存在,或者在规则调用后文件被替换了。这允许规则在升级程序可执行文件后或甚至在其安装之前继续运行。
  • 记录安全事件
    pam_faillock 认证模块能够记录失败的登录尝试。也可以将审计设置为记录失败的登录尝试,并提供有关试图登录的用户的附加信息。
  • 搜索事件
    审计提供了 ausearch 工具,可用于过滤日志条目,并根据多个条件提供完整的审计跟踪。
  • 运行总结报告
    aureport 实用程序可用于生成记录事件的日常报告等。然后,系统管理员可以分析这些报告,并进一步调查可疑的活动。
  • 监控网络访问
    iptablesebtables 工具可以配置为触发审计事件,允许系统管理员监控网络访问。

    系统性能可能会受到影响,具体取决于审计所收集的信息量。

审计系统架构

审计系统由两个主要部分组成: 用户空间应用程序和工具 ,以及 内核端系统调用处理 。内核组件接收用户空间应用程序的系统调用,并通过以下过滤器对其进行过滤: usertaskfstypeexit[1]

用户空间审计守护进程 从内核收集信息,并在日志文件中创建条目。其他审计用户空间工具审计守护进程内核审计组件审计日志文件 进行交互:

  • audisp - Audit 分配程序守护进程与 Audit 守护进程交互,并将事件发送到其他应用程序,以便进一步处理。此守护进程的目的是提供插件机制,以便实时分析程序可以与审计事件交互。
  • auditctl - 审计控制实用程序与内核审计组件交互,以管理规则并控制事件生成进程的多个设置和参数。
  • 其余的审计工具会将审计日志文件的内容作为输入,并根据用户的要求生成输出。例如,aureport 工具生成所有记录的事件的报告。
阅读全文 »

Linux 系统安全加固常用方法

服务网络安全

  • 启用防火墙,并确保入口流量都是必须的,禁止无关的 IP 访问目标主机上的服务(端口)

系统软件安全检测

  • 定期扫描系统上安装的软件,确保关键系统命令未被篡改,例如使用 rpm -Va 对所有系统上的软件进行校验,检查是否有软件被篡改

    # rpm -Va
    .......T. /usr/src/kernels/3.10.0-1160.114.2.el7.x86_64/virt/lib/Kconfig
    .......T. /usr/src/kernels/3.10.0-1160.114.2.el7.x86_64/virt/lib/Makefile
    S.5....T. c /root/.bash_profile
    S.5....T. c /root/.bashrc
    .M....... /var/run/supervisor
    missing /etc/filebeat/fields.yml
    SM5....T. c /etc/filebeat/filebeat.yml
    ....L.... c /etc/pam.d/fingerprint-auth
    ....L.... c /etc/pam.d/password-auth
    ....L.... c /etc/pam.d/postlogin
    ....L.... c /etc/pam.d/smartcard-auth
    ....L.... c /etc/pam.d/system-auth

    输出的每一行对应一个文件,前 9 个字符的字符串显示了该文件的属性状态。每个字符的位置代表了特定的属性检查结果。rpm -Va 对比的是当前系统中文件的状态与 RPM 数据库中记录的文件状态。

    每个字符的含义:

    • 第 1 位 : 文件类型 (S).
      如果文件丢失了,则会显示 S(代表文件缺失,”File is missing”)。
    • 第 2 位:文件大小 (5)
      如果文件大小与 RPM 数据库中的记录不一致,则会显示 5
    • 第 3 位:文件权限(模式/权限位,M)
      如果文件的权限与 RPM 数据库记录的不一致,则会显示 M
    • 第 4 位:文件的所有者 (U)
      如果文件的所有者与 RPM 数据库记录的不一致,则会显示 U
    • 第 5 位:文件所属的组 (G)
      如果文件的所属组与 RPM 数据库记录的不一致,则会显示 G
    • 第 6 位:文件的设备类型 (D)
      如果文件的设备类型(如块设备或字符设备)与 RPM 数据库记录的不一致,则会显示 D
    • 第 7 位:文件的时间戳 (T)
      如果文件的修改时间与 RPM 数据库中的记录不一致,则会显示 T
    • 第 8 位:文件的校验和 (5)
      如果文件内容的校验和与 RPM 数据库记录的不一致,则会显示 5
    • 第 9 位:文件的符号链接 (L)
      如果文件是一个符号链接,并且符号链接目标发生变化,则会显示 L
    • 如果是配置文件,会被标记为 c

文件加固

文件系统加固

Linux 操作系统中的很多目录都有约定的用途,可能会挂载单独的文件系统,不同用途的目录,对权限的要求不同,从安全角度考量,可以针对文件系统进行一定程度的安全加固。

文件系统的挂载,主要依赖配置文件 /etc/fstab,此配置会被 mountdumpfsck 等命令使用,其权限应该设置为 644,属主和属组都应该是 root。在挂载不同用途的文件系统时,可以根据其用途配置权限限制。以下列出部分示例

可用的挂载选项可以查看 man fatabman mountman 5 ext4 等内容中的选项,不同的文件系统支持不同的挂载选项,通用的挂载选项(独立于文件系统)可以查看 man mount 中的 FILESYSTEM-INDEPENDENT MOUNT OPTIONS 部分

  • /home/ 目录下通常是用户家目录,可能会挂载到单独的文件系统,根据其特性,可以配置以下限制
    • nosuid : 禁止其中的文件/目录配置 SUID 或 SGID 权限
    • nodev : 禁止其中的设备被内核识别,放置在此目录下的设备可能都是恶意设备,应该被禁止识别并使用
    • noexec : 禁止此文件系统中的可执行文件执行。
  • /tmp/ 目录也可以设置以下限制
    • nosuid
    • nodev
    • noexec

关键文件审计及监控

auditd 审计

可以使用 `auditd` 服务对系统上的关键文件进行审计日志记录

关键文件监控

系统上的某些关键文件,如常用可执行文件(/sbin/ 下的文件)、关键配置文件等,要监控其是否被恶意修改。可以参考以下方法

  • find 命令搜索文件修改时间
    find 命令的 -mtime 可以查找文件的 内容修改时间

    find 命令的 -ctime 可以查找文件的 创建时间/属性修改时间

    如常用的系统命令不会出现内容的修改和属性的修改,如果出现这些现象,很可能属于恶意篡改,可以使用 find 命令查找或是监控这些变化

    # find /sbin -mtime -1
    /sbin
    /sbin/init
    /sbin/reboot

    在发现关键文件被篡改后可以及时发送告警。可以使用 stat 命令检查文件变更的更详细信息

    # stat /sbin/init
    File: '/sbin/init' -> '../bin/systemd'
    Size: 14 Blocks: 0 IO Block: 4096 symbolic link
    Device: fd01h/64769d Inode: 9551 Links: 1
    Access: (0777/lrwxrwxrwx)
    Uid: ( 0/ root) Gid: ( 0/ root)
    Context: system_u:object_r:bin_t:s0
    Access: 2016-02-03 03:34:57.276589176 -0500
    Modify: 2016-02-02 23:40:39.139872288 -0500
    Change: 2016-02-02 23:40:39.140872415 -0500
    Birth: -

    为了更好的监控关键文件的篡改,可以在系统运行之初就为其创建一个包含关键文件的 mtimesctimes 信息的数据库,并在系统运行过程中通过脚本检测关键文件的 mtimesctimes 并和原始数据库中的信息进行对比已检测文件是否被篡改。通常的 Intrusion Detection System 基本都实现了类似的功能。

    通常需要关注的可以被 find 检查的其他特殊类型文件和特殊权限还可能包括以下事项:

    File or Settings Scan Command Problem With File or Settings
    SUID find / -perm -4000 Allows anyone to become the file’s owner temporarily while the file is being executed in memory
    GID find / -perm -2000 Allows anyone to become a group member of the file’s group temporarily while the file is being executed in memory.
    rhost files find /home -name .rhosts Allows a system to trust another system completely. It should not be in /home directories.
    Ownerless files find / -nouser Indicates files that are not associated with any username.
    Groupless files find / -nogroup Indicates files that are not associated with any group name.

Viruses

ClamAV

ClamAV 是一个开源并免费的 Linux 杀毒(Antivirus Software)软件。

Rootkit

chkrootkit

chkrootkit 是 Linux 上常用的检测 rootkit 的工具,这个工具的结果需要更深入的分析,它可能出错

# chkrootkit | grep INFECTED
Checking 'du'... INFECTED
Checking 'find'... INFECTED
Checking 'ls'... INFECTED
Checking 'lsof'... INFECTED
Checking 'pstree'... INFECTED
Searching for Suckit rootkit... Warning: /sbin/init INFECTED

Rootkit Hunter

Rootkit Hunter 是另一个比较出名的 rootkit 检测工具

Intrusion Detection and Prevention System

入侵检测和防御系统 可以监控系统上的活动并找到潜在的恶意活动或者进程并报告相关活动。Linux 上常用的入侵检测系统有

  • aide : Advanced Intrusion Detection Environment.
  • snort
  • tripwire

传统的 PC 架构计算机使用 Master Boot Record(MBR)分区表(Partition Tables) 来存储计算机上的 磁盘分区(Disks Partitions) 信息。MBR 有以下特点:

  • MBR 的分区最大支持 2TB 的容量。

最新的 UEFI 计算机架构使用 GUID(Globally Unique Identifier) Partition Tables(GPT) 标准来替代旧的 BIOS 方法启动计算机操作系统。相比于 MBR,GPT 有以下优势及特性:

  • GPT 的分区最大能支持到 9.4ZB

传统的基于 MBR Partition Tables 的最重要的分区工具是 fdisk,但是它目前不支持 GPT Partitions ,新的工具 parted 正在顶替 fdisk 的功能。

parted 用法

要查看 parted 常见用法,可以参考 parted --help 或在交互模式中使用 help 指令

查看分区表信息

要查看系统上的分区信息,使用以下方式之一

  • parted -l
    # parted -l
    Model: Amazon Elastic Block Store (nvme)
    Disk /dev/nvme0n1: 85.9GB
    Sector size (logical/physical): 512B/512B
    Partition Table: gpt
    Disk Flags:

    Number Start End Size File system Name Flags
    14 1049kB 5243kB 4194kB bios_grub
    15 5243kB 116MB 111MB fat32 boot, esp
    1 116MB 85.9GB 85.8GB ext4


    Model: Amazon Elastic Block Store (nvme)
    Disk /dev/nvme1n1: 107GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos
    Disk Flags:

    Number Start End Size Type File system Flags
    1 1049kB 53.7GB 53.7GB primary ext4


    Model: Unknown (unknown)
    Disk /dev/zram0: 33.2GB
    Sector size (logical/physical): 4096B/4096B
    Partition Table: loop
    Disk Flags:

    Number Start End Size File system Flags
    1 0.00B 33.2GB 33.2GB linux-swap(v1)

  • parted 交互模式,在交互模式中使用指令 p
    # parted 
    GNU Parted 3.4
    Using /dev/nvme0n1
    Welcome to GNU Parted! Type 'help' to view a list of commands.

    (parted) p
    Model: Amazon Elastic Block Store (nvme)
    Disk /dev/nvme0n1: 85.9GB
    Sector size (logical/physical): 512B/512B
    Partition Table: gpt
    Disk Flags:

    Number Start End Size File system Name Flags
    14 1049kB 5243kB 4194kB bios_grub
    15 5243kB 116MB 111MB fat32 boot, esp
    1 116MB 85.9GB 85.8GB ext4

    (parted)

创建 GPT 分区格式的硬盘

要使用 parted 对硬盘指定其分区表类型,假设硬盘为 /dev/nvme1n1 (默认表示第二个 NVM(NVMe, NonVolatile Memory Disks express, NVM 磁盘设备专用的通信接口协议) 硬盘的第一个 Namespace),参考以下步骤:

  1. parted /dev/nvme1n1 ,进入交互模式并对指定的硬盘进行分区操作, 以下步骤会导致硬盘上所有的分区及数据丢失
  2. 在交互模式中使用 mklabel gpt 命令,配置硬盘使用 GPT 类型的分区表,而不是 MBR
    (parted) mklabel gpt
    Warning: The existing disk label on /dev/nvme1n1 will be destroyed and all data
    on this disk will be lost. Do you want to continue?
    Yes/No? Yes
    (parted)
  3. 在交互模式中使用 mkpart 命令进行分区操作,分区完成后使用 p 指令检查分区
    (parted) mkpart
    Partition name? []? alldisk
    File system type? [ext2]? xfs
    Start? 1
    End? 123GB

    (parted) p
    Model: SanDisk Ultra (scsi)
    Disk /dev/nvme1n1: 123GB
    Sector size (logical/physical): 512B/512B
    Partition Table: gpt
    Disk Flags:
    Number Start End Size File system Name Flags
    1 1049kB 123GB 123GB xfs alldisk
  4. 使用 quit 指令退出 parted 交互模式。

    fdisk 交互模式中,只有最终执行了 w 命令保存,对硬盘的操作才会最终生效,和 fdisk 不同,parted 命令对硬盘的更改立即生效

  5. 对分区进行格式化并挂载使用,如果需要持久化挂载(系统重启后依然生效),可以将挂载信息写入 /etc/fstab
    mkfs -t xfs /dev/nvme1n1p1
    mount /dev/nvme1n1p1 /mnt/

文件权限

在 Linux 系统中,普通的文件权限控制通过关联身份三元组 (user, group,other) 和权限三元组 (r, w, x) 来实现访问控制。

系统存在一个 umask 值(针对用户),umask 是一个权限掩码,它决定了新建的文件或者目录的默认权限,使用 umask 命令可以查看当前(用户) 的 umask

$ umask
0022

比如如上所示的 umask 值,决定了当前(用户)创建的文件和目录的默认权限

  • 目录 - 默认权限为 0755777-022),即 rwxr-xr-x
  • 文件 - 默认权限为 644 (666-022),即 rw-r--r--

因此要配置当前(用户)创建的文件或者目录的默认权限,只需要配置合适的 umask 值即可。配置 umask 值可以通过以下方法

  • 临时方法
    umask 027
  • 永久方法
    根据需求将 umask 027 配置添加到配置文件中,如 /etc/profile~/.bashrc~/.bash_profile

如果需要更进一步的权限控制,需要使用到 Sticky Bit 和 ACL,更细力度的控制还包括 SELinux. 相关扩展权限标志如下:

  • 文件/目录 权限最后会包含一个 . : 表示 SELinux (Security Enhanced Linux)扩展权限。可以使用命令 ls -l -Z 查看具体权限。
  • 文件/目录 权限最后会包含一个 + : 表示 文件/目录ACL(Access Control List) 扩展权限,相关操作及命令参考
  • 目录 权限最后会包含一个 t : 表示此 目录Sticky Bit 扩展权限,相关操作及命令参考
  • 可执行文件 权限中属主(Owner)的 x 位变为 s : 表示此 可执行文件 配置了 Set UID 扩展权限
  • 可执行文件/目录 权限中属组(Group)的 x 位变为 s : 表示此 目录 配置了 Set GID 扩展权限

Linux 文件权限控制中,除了 SELinux 权限,其他权限控制属于 DAC(Discretionary Access Control),SELinux 属于 MAC(Mandatory Access Control),系统执行权限控制的过程中, 如果 DAC 权限允许资源访问,会继续进行 SElinux 权限检查,如果 DAC 权限拒绝资源访问,不会再进行 SELinux 权限检查

Set UID

  • 只有 可执行的二进制程序和可执行的代码 才能设定 SUID 权限。
  • 命令执行者首先要对该程序拥有 x(执行)权限。
  • 命令执行者在执行该程序时获得该程序文件 属主(Owner) 的身份。
  • SetUID 权限只在该程序 执行过程中 有效,也就是说身份改变只在执行过程中有效。

设定 SUID 和 SGID 时,传统的 3 元组权限方式(如 rwxrwxrwx = 777) 变为 4 元组(Srwxrwxrwx),其中的 S 选项包括:

  • 4 代表 SUID,如 4777
  • 2 代表 GID,如 2777
  • 1 代表 Sticky BIT,如 1777
  • 7 代表全部设置, 如 7777

SUID 设定命令格式:

chmod 4777 可执行文件名

chmod u+s 可执行文件名

取消 SUID 设置:

chmod 777 可执行文件名

假如某个可执行文件的属主为 root,其设置了 SUID,普通用户运行此可执行文件时会暂时拥有 root 的权限,有一定的风险存在,因此要谨慎设置,为系统安全考虑,要定期查找系统上拥有 SUID 权限的可执行文件并核对其是否存在风险。

Set GID

可执行文件 来说,SGID 拥有和 SUID 同样的作用,只不过 **命令执行者在执行该程序时获得该程序文件 属组(Group) 的身份。

SGID 设定方法:

chmod 2777 可执行文件名

chmod g+s 可执行文件名

Sticky Bit

粘滞位 (Sticky Bit) 只能用于目录,并对其中的文件有特殊的权限控制。他的主要作用是确保只有文件的所有者才能够删除或者修改文件。要给某个目录配置 粘滞位 (Sticky Bit) ,使用以下命令

chmod +t directoryname

这将为目录 directoryname 配置粘滞位 (Sticky Bit),以下命令可以验证 粘滞位 (Sticky Bit)是否存在。如果目录的权限列表中有 t 标志,表示目录设置了 粘滞位 (Sticky Bit)

$ ls -l directoryname
drwxrwxrwt 2 owner group 4096 Jun 26 10:15 directoryname

设置粘滞位后,只有文件的所有者才能删除或修改该文件。其他用户即使有写权限(w),也无法删除其他用户的文件。

阅读全文 »

systemd-journald 服务简介

systemd-journald 服务是 systemd init 系统提供的收集系统日志的服务。它会根据从内核、用户进程、标准输入和系统服务错误收到的日志记录信息,维护结构化的索引日记,并以此方式来收集和储存日志记录数据。systemd-journald 服务默认处于启用状态。

默认情况下,systemd-journald/run/log/journal/ 中储存日志数据。由于 /run/ 目录具有易失本性,因此,在重引导时会丢失日志数据。要永久保存日志数据,/var/log/journal/ 目录必须存在且具有正确的所有权和权限,如此,systemd-journald 服务便可在其中储存其数据。

要在终端中查看日志信息,可以使用命令 journalctl

systemd-journald 服务常用配置

持久化日志存储

默认情况下,日志位于 /run/log/journal/,重启后日志会丢失,为了持久化日志,可按照以下 2 种方法之一配置

  • 方法 1

    1. root 身份打开 /etc/systemd/journald.conf 进行编辑
      vi /etc/systemd/journald.conf
    2. 将包含 Storage= 的行取消注释,并将它更改为 Storage=persistent
      /etc/systemd/journald.conf
      [Journal]
      Storage=persistent
      #Compress=yes
      SystemMaxUse=50M
      [...]
    3. 重启 systemd-journald
      systemctl restart systemd-journald
      之后日志会持久化存储于 /var/log/journal。这些数据最多会占用 /var/log/journal 所在文件系统空间的 10%,要更改此限制,可以修改选项 SystemMaxUse=50M
阅读全文 »

在 Linux 中,命令提供的 man 手册是一份非常详细的命令使用说明手册,要了解命令的使用方法及其工作原理,熟练参考 man 手册是及其必要的。

man 手册中不仅包含了命令的使用方法,还包括了命令相关的 (配置)文件说明System Calls 等相关信息,下表中列出了 man 手册不同编号对应的功能

Section Number Section Name Description
1 User Commands 用户可以在 shell 中运行的指令说明
man 命令不指定 Section Number 时默认为 1
2 System Calls 应用程序中的功能函数调用的内核函数
3 C Library Functions 应用程序针对特定的函数库提供的接口
4 Devices and Special Files 程序使用的硬件或软件
5 File Formats and Conventions 涉及的文件类型(如配置文件)及约定
6 Games
7 Miscellaneous 其他杂项,如 协议文件系统字符集
8 System Administration Tools and Daemons 需要 root 权限或其他管理员权限运行的命令

要查看命令 man 的某个部分,可以使用以下命令查看 passwd 命令的 File Formats and Conventions

man 5 passwd

环境信息

  • Centos 7

为源码编译安装的软件安装 man 手册

使用源码编译安装的软件默认是没有 man 手册的,使用 man 命令会报以下错误

$ man fswatch
No manual entry for fswatch

要为源码编译安装的软件安装 man 手册,可以参考以下步骤,此处示例软件为 fswatch,软件编译安装到了 /usr/local/fswatch-1.17.1/

  1. 一般情况下,源码中会附带软件的使用文档,编译安装后,可能位于以下路径,fswatch 编译安装后的 man 手册位于 /usr/local/fswatch-1.17.1/share/man/man7/fswatch.7

    ls /usr/local/fswatch-1.17.1/doc
    ls /usr/local/fswatch-1.17.1/share/doc
    ls /usr/local/fswatch-1.17.1/share/man/

  2. man 命令使用的文档默认来源于 /usr/share/man/

    $ ls /usr/share/man/
    cs de fr hu it ko man1 man1x man2x man3p man4 man5 man6 man7 man8 man9 mann pl pt_BR ro sk tr zh_CN
    da es hr id ja man0p man1p man2 man3 man3x man4x man5x man6x man7x man8x man9x nl pt pt_PT ru sv zh zh_TW

    要为编译安装软件的安装 man 帮助文档,首先将 fswatch 的帮助文档复制到 man 页面的目录

    cp /usr/local/fswatch-1.17.1/share/man/man7/fswatch.7 /usr/share/man/man7/

  3. 更新 man 索引

    $ mandb
    1 man subdirectory contained newer manual pages.
    47 manual pages were added.

    安装成功后,可以正常使用 man fswatch 查看帮助文档。

bash 快捷键

bash 常用的快捷键总结

删除类快捷键

快捷键 功能 示例
Ctrl + D 删除光标右侧的一个字符,等于 Delete
Ctrl + H 删除光标左侧的一个字符,等于 Backspace
Ctrl + K 删除从光标位置到行尾的所有字符。
Ctrl + U 删除从光标位置到行首的所有字符。
Ctrl + W 删除光标左侧的一个单词(以空格为分隔)。
Alt + D 删除光标右侧的一个单词。(空格,下划线,点分割)
Ctrl + C 删除整行

定位类快捷键

快捷键 功能 示例
Ctrl + F 向前挪动一个字符 ,等于 右箭头 ->
Ctrl + B 向后挪动一个字符 ,等于 左箭头 <-
Alt + F 向前挪动一个 word
Alt + B 向后挪动一个 word 。
Ctrl + A 跳到行首。
Ctrl + E 跳到行尾。

Recall 类快捷键

bash 中执行过的命令都保存在了历史记录中,可以通过 history 命令查看。为了快速重新执行或者修改之前的命令并执行,bash 提供了以下快捷键

快捷键 功能 示例
Ctrl + R 搜索 history最后一个 匹配的命令
Alt + P 搜索 history最常使用 的命令
!100 重新执行 history 中的第 100 号的命令,无确认,会立即执行
!! 重新执行 history 中的 最后一个 命令,无确认,会立即执行

bash 环境变量

shell 中的环境变量大体可以分为以下几种:

  • Local Variables : 当前 Shell 中的 所有的本地变量(Local Variables ,要查看所有的 本地变量(Local Variables),可以使用以下命令:

    • set
    • declare
      $ set | more
      BASH=/bin/bash
      BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:progcomp:promptvars:sour
      cepath
      BASH_ALIASES=()
      BASH_ARGC=([0]="0")
      BASH_ARGV=()
      ...
  • Environment Variables : 本地变量(Local Variables)的一部分子集(subset)被稱為 环境变量(Environment Variables环境变量(Environment Variables 会被导入到任何从当前 Shell 启动的新的 Shell,要查看 环境变量(Environment Variables ,使用以下命令

    • env
    • printenv
      $ env
      SHELL=/bin/bash
      SESSION_MANAGER=local/U-3TSDMAL9IVFAQ:@/tmp/.ICE-unix/3396,unix/U-3TSDMAL9IVFAQ:/tmp/.ICE-unix/3396
      QT_ACCESSIBILITY=1
      COLORTERM=truecolor
      XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
      SSH_AGENT_LAUNCHER=gnome-keyring
      XDG_MENU_PREFIX=gnome-
      GNOME_DESKTOP_SESSION_ID=this-is-deprecated
      GTK_IM_MODULE=fcitx
      LANGUAGE=en
      LC_ADDRESS=en_US.UTF-8
      GNOME_SHELL_SESSION_MODE=ubuntu
      LC_NAME=en_US.UTF-8
      SSH_AUTH_SOCK=/run/user/408001114/keyring/ssh
      XMODIFIERS=@im=fcitx
      DESKTOP_SESSION=ubuntu
      LC_MONETARY=en_US.UTF-8
      GTK_MODULES=gail:atk-bridge
      DBUS_STARTER_BUS_TYPE=session
      ...
      查看单个变量
      $ echo $PATH 
      /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin

bash 常用环境变量

环境变量 功能 示例
PATH 可执行文件查找路径变量。
查找顺序从左向右,找到即停止
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
PS1
PS[234]
PS1 环境变量定义了 bash 中的命令后提示符包含的内容
定义中支持的元字符可以查看 man bash 手册
PS1="[\u@\h \W]\\$

bash 命令查找优先级

bash 中命令执行优先顺序如下:

  • Aliases : 由 alias 命令配置的命令别名。
  • Shell 预留的关键字 : 主要是 Shell 编程中会用到的关键字,如 dowhilecaseelse 等。
  • Built-in Command : shell 内嵌的命令,如 cdecho
  • Filesystem Command : 环境变量 PATH 中的命令。

要查找命令所在位置,可以使用 typewhich 命令

$ type bash
bash is /usr/bin/bash

$ which bash
/usr/bin/bash

$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls

如果要查找命令所在的所有位置,可以使用 type -a ls,如上所示,这会显示 ls 命令所在的所有位置

bash 环境变量配置优先级

Linux 系统中的多个配置文件中可以配置环境变量,其中有些会针对所有的用户和 shell 生效,有些只会针对特定的用户生效。

以下表格中列出了常用的环境变量的配置文件:

File Description
/etc/profile 此配置中的环境变量对所有用户生效,在用户登陆时为其配置环境变量 ,它一般会加载(包含)/etc/profile.d 中的配置
/etc/bashrc 此配置中的环境变量针对所有的 shell 生效,每次打开一个 bash 时会执行 ,一般会设置包括 登陆提示alias
~/.bash_profile 此配置中的环境变量对 当前登陆 用户生效,仅在用户登陆时为其配置环境变量 ,一般会加载 ~/.bashrc 文件
~/.bashrc 此配置中的环境变量针对 当前登陆 的用户 bash 生效,并在用户打开每个新的 bash 时执行
~/.bash_logout 此配置中的环境变量对 当前登陆 用户生效,仅在 当前登陆用户登出(logout) 时执行

环境信息

  • centos 7
  • Python 3.10
  • Django 4.0
  • uwsgi 2.0.20
  • nginx 1.20.1
  • venv

    示例中虚拟环境位于 /opt/vb/, Django工程目录位于 /opt/vb/vb/ , 工程名称为vb

uwsgi 配置文件 (uwsgi.ini) 配置示例

uwsgi.ini
[uwsgi]
socket = 127.0.0.1:8081
chdir = /opt/vb/vb
wsgi-file = ./vb/wsgi.py
master = true //主进程
vhost = true //多站模式
no-site = true //多站模式时不设置入口模块和文件
workers = 2 //子进程数
reload-mercy = 10
vacuum = true //退出、重启时清理文件
max-requests = 1000
limit-as = 512
buffer-size = 30000
pidfile = uwsgi-8081.pid
daemonize = uwsgi-8081.log
pythonpath = /opt/vb/env/lib/python3.10/site-packages/
阅读全文 »

Nginx 服务配置

全局通用配置

nginx.conf
user nginx nginx;    

# 建议设置为 cpu 核心数或者 cpu 核心数的 2 倍,进程会包含一个 `master process`,多个 `worker process`
# master process 负责绑定端口、调度进程等,不负责业务的处理
# worker process 是业务进程,负责业务的处理
worker_processes auto;

# 一个 worker 进程可以打开的最大的 fd 个数,受 Linux 内核限制
# 理论值应该是系统最多打开文件数(ulimit -n)与 nginx 进程数相除
# 可通过 ulimit 设置或修改系统文件:`/etc/securit/limits.conf`
worker_rlimit_nofile 1024;

# cpu 亲和性设置
worker_cpu_affinity 0001 0010 0100 1000;

# 工作进程调度优先级,-20 到 19 之间的值,值越小越优先调用。
# 如果系统同时运行多个任务,你可能需要提高 nginx 的工作进程的优先级
worker_priority 0;

# ssl 硬件加速服务器,需要硬件支持
# ssl_engine ssl_engine device;

# nginx 是否以守护进程运行,是否让 nignx 运行于后台;调试时可为 off,使得所有信息直接输出在控制台
daemon on | off;

# events 模块中包含 nginx 中所有处理连接的设置。
events {
# 每个 worker 进程允许的最多连接数,
# nginx 服务最大连接数:worker_processes * worker_connections (受 worker_rlimit_nofile 限制)
worker_connections 1024;
use epoll;

# 是否允许一次性地响应多个用户请求
multi_accept on;

# 是否打开 nginx 的 accept 锁;此锁能够让多个 worker 进行轮流地、序列化地与新的客户端建立连接;
# 而通常当一个 worker 进程的负载达到其上限的 7/8,master 就尽可能不将请求调度至 worker.
accept_mutex on | off;
}

# HTTP 模块控制着 nginx http 处理的所有核心特性
http {
include mime.types;
default_type application/octet-stream;

# 是否在错误页面中显示和响应头字段中发出 nginx 版本号。
# 安全考虑建议关闭
server_tokens on | off | string;

# 是否启用 sendfile 内核复制模式功能。作为静态服务器可以提供最大的 IO 访问速度。
sendfile on | off;

# 尽快发送数据,否则会在数据包达到一定大小后再发送数据。这样会减少网络通信次数,降低阻塞概率,但也会影响响应及时性。
# 比较适合于文件下载这类的大数据通信场景。
tcp_nodelay on|off;

# 单位s,适当降低此值可以提高响应连接数量
keepalive_timeout 65;

# 一次长连接上允许的最大请求数
keepalive_requests 100;

# 禁止指定浏览器使用 keepalive
keepalive_disable msie6|none;

# 读取 http 请求首部的超时时长。如果客户端在此时间内未传输整个头,则会向客户端返回 408(请求超时)错误
client_header_timeout 1;

# 读取 http 请求包体的超时时间。
client_body_timeout 2;

# 发送响应的超时时长。超时后连接将关闭。
send_timeout 5;

# http 请求包体的最大值,常用于限定客户端所能够请求的最大包体,根据请求首部中的 Content-Length 来检查,以避免无用的传输。
client_max_body_size 1m;

# 限制客户端每秒传输的字节数,默认为0,表示没有限制。单位 Byte/s
limit_rate 0;

# nginx 向客户端发送响应报文时,如果大小超过了此处指定的值,则后续的发送过程开始限速,单位 Byte
limit_rate_after 0;

# 是否忽略不合法的 http 首部,默认为 on,off 意味着请求首部中出现不合规的首部将拒绝响应。
ignore_invalid_headers on|off;

# 用户访问的文件不存在时,是否将其记录到错误日志中。
log_not_found on|off;

# nginx 使用的 dns 地址,及缓存解析结果的时间
resolver 8.8.8.8 [valid=time] [ipv6=on|off];

# dns 解析超时时间
resolver_timeout 2;

# 是否打开文件缓存功能,max:用于缓存条目的最大值,
# inactive:某缓存条目在指定时长内没有被访问过时,将自动被删除,即缓存有效期,通常默认为 60s。
open_file_cache off;
open_file_cache max=N [inactive=time];

# 是否缓存文件找不到或没有权限访问等相关信息。
open_file_cache_errors on | off;

# 多长时间检查一次缓存中的条目是否超出非活动时长。
# 建议值:小于等于 open_file_cache inactive
open_file_cache_valid 60;

# 在 open_file_cache inactive指 定的时长内被访问超过此处指定的次数时,才不会被删除(删除低命中率的缓存)。
open_file_cache_min_uses 2;

# 开启内容压缩,可以有效降低客户端的访问流量和网络带宽
gzip on | off;

# 内容超过最少长度后才开启压缩,太短的内容压缩效果不佳,且会浪费系统资源。
# 压缩长度会作为 http 响应头 Content-Length 字段返回给客户端。 建议值:64
gzip_min_length length;

# 压缩级别,默认值为 1。范围为1~9级,压缩级别越高压缩率越高,但对系统性能要求越高。建议值:4
gzip_comp_level 1~9;

# 压缩内容类型,默认为 text/html;。只压缩 html 文本,一般我们都会压缩 js、css、json 之类的,可以把这些常见的文本数据都配上。
如:text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_types mime-type …;

# 自动显示目录
autoindex on;

# off : 以人类易读的方式显示文件大小,on:以 bytes 显示文件大小
autoindex_exact_size off;

# 定义限制区域,imit_req_zone 只能放在 http {} 内,使用此限制可以在 http {} (对服务器内所有的网站生效)、server {} (对具体的一个网站生效)或 location {} (对具体的一个网址生效)
# 此区域名称为 test,可根据需求自定义; 10m 表示此区域存储 key($binary_remote_addr)使用的大小
# 存储大小,一般 1m 空间大约能保存 1.6 万条 IP 地址,空间满了新数据会覆盖旧数据
# rate=1r/m ,限制访问请求频率为每分钟 1 次,可根据需要自行设置,1r/s 是 1 秒 1 次,时间单位只能选择 s (秒)或 m (分),最低频率限制是每分钟 1 次访问请求
# rate=10r/m,1分钟最多访问 10 次,同时不能超过 1r/6s,即 6s 内最多访问 1 次。超过 1r/6s 返回 503
limit_req_zone $binary_remote_addr zone=test:10m rate=1r/m;

# 定义日志格式
log_format main '{ time: $time_iso8601|'
'http_host:$http_host|'
'cdn_ip:$remote_addr|'
'request:$request|'
'request_method:$request_method|'
'http_user_agent:$http_user_agent|'
'size:$body_bytes_sent|'
'responsetime:$request_time|'
'upstreamtime:$upstream_response_time|'
'upstreamhost:$upstream_addr|'
'upstreamstatus:$upstream_status|'
'url:$http_host$uri|'
'http_x_forwarded_for:$clientRealIp|'
'status:$status}';

# server 负责具体的 http 服务器实现
server {
listen 80 [default_server] [rcvbuf=SIZE] [sndbuf=SIZE] [ssl];

# 可使用通配符*或正则表达式(~开头),多个域名先精确匹配,再通配,再正则,'_'表示空主机头
server_name _ ;

access_log logs/access.log main;
error_log logs/access.err.log;

# 跨域配置
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers 'Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With';
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
add_header Access-Control-Allow-Credentials: true;

location / {
# web 资源路径
root html;

# 定义默认页面,从左往右匹配
index index.html index.htm;

# 自左向右读取指定路径,找到即停止,如果都不存在,返回一个错误码
try_files $uri $uri.html $uri/index.html =404;

# 自左向右读取指定路径,找到即停止,如果都不存在,返回一个 uri
try_files $uri $uri.html $uri/index.html /404.html;
}

location /i/ {
# 路径别名,只能用于 location 中。
# 访问 http://a.com/i/a.html, 资源路径为:/data/www/html/a.html
# 若是root指令,访问 http://a.com/i/a.html,资源路径为:/data/www/html/i/a.html
alias /data/www/html/;
}

# 对于某个请求发生错误,如果匹配到错误码,重定向到新的 url
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# 对于某个请求发生错误,如果匹配到错误码,重定向到新的 url,同时可以更改返回码
error_page 404 =200 /404.html;
}

# 包含其他配置文件
include vhosts/*.conf;
}


阅读全文 »

nftables 是一个 netfilter 项目,旨在替换现有的 {ip,ip6,arp,eb}tables 框架,为 {ip,ip6}tables 提供一个新的包过滤框架、一个新的用户空间实用程序(nft)和一个兼容层(iptables-nft)。它使用现有的钩子、链接跟踪系统、用户空间排队组件和 netfilter 日志子系统。

在 Linux 内核版本高于 3.13 时可用

它由三个主要组件组成:

  • 内核实现: 内核提供了一个 netlink 配置接口以及运行时规则集评估
  • libnl netlink : libnl 包含了与内核通信的基本函数
  • nftables : 用户空间前端。nftables 的用户空间实用程序 nft 评估大多数规则集并传递到内核。规则存储在链中,链存储在表中。

iptables 不同点

  • nftables 在用户空间中运行,iptables 中的每个模块都运行在内核(空间)中
  • 表和链是完全可配置的。在 nftables 中,表是没有特定语义的链的容器。iptables 附带了具有预定义数量的基链的表,即使您只需要其中之一,所有链都已注册,未使用的基础链也会损害性能。
  • 可以在一个规则中指定多个操作。在 iptables 中,您只能指定一个目标。这是一个长期存在的局限性,用户可以通过跳到自定义链来解决,但代价是使规则集结构稍微复杂一些。
  • 每个链和规则没有内置计数器。在 nftables 中,这些是可选的,因此您可以按需启用计数器。由于 iptables 内置了一个数据包计数器,所以即使这些内置的链是空的,也会带来性能损耗
  • 更好地支持动态规则集更新。在 nftables 中,如果添加新规则,则剩余的现有规则将保持不变,因为规则集以链表形式表示,这与整体式 blob 表示相反,后者在执行规则集更新时内部状态信息的维护很复杂。
  • 简化的双堆栈 IPv4/IPv6 管理,通过新的 inet 系列,可让您注册同时查看 IPv4 和 IPv6 流量的基链。 因此,您不再需要依赖脚本来复制规则集。

服务名称默认为 nftables,默认配置文件为 /etc/nftables.conf ,其中已经包含一个名为 inet filter 的简单 ipv4/ipv6 防火墙列表。

/etc/nftables.conf
#!/usr/sbin/nft -f

flush ruleset

table inet filter {
chain input {
type filter hook input priority 0;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}

nftables 服务的 systemd 配置文件如下:

/lib/systemd/system/nftables.service
[Unit]
Description=nftables
Documentation=man:nft(8) http://wiki.nftables.org
Wants=network-pre.target
Before=network-pre.target shutdown.target
Conflicts=shutdown.target
DefaultDependencies=no

[Service]
Type=oneshot
RemainAfterExit=yes
StandardInput=null
ProtectSystem=full
ProtectHome=true
ExecStart=/usr/sbin/nft -f /etc/nftables.conf
ExecReload=/usr/sbin/nft -f /etc/nftables.conf
ExecStop=/usr/sbin/nft flush ruleset

[Install]
WantedBy=sysinit.target

nftables 使用的内核模块如下,加载这些模块,服务才能正常运行

# lsmod | grep nf
nf_log_syslog 20480 1
nft_chain_nat 16384 17
nf_nat 49152 3 xt_nat,nft_chain_nat,xt_MASQUERADE
nf_conntrack_netlink 49152 0
nft_counter 16384 142
nf_reject_ipv4 16384 1 ipt_REJECT
nf_conntrack 172032 6 xt_conntrack,nf_nat,xt_state,xt_nat,nf_conntrack_netlink,xt_MASQUERADE
nf_defrag_ipv6 24576 1 nf_conntrack
nf_defrag_ipv4 16384 1 nf_conntrack
nft_compat 20480 143
nf_tables 249856 570 nft_compat,nft_counter,nft_chain_nat
nfnetlink 20480 5 nft_compat,nf_conntrack_netlink,nf_tables,ip_set
阅读全文 »

Outline 官网

Outline 是由附属于 Google 的 Jigsaw 开发的开源的 VPN 软件。它的设计目标是为了实现 VPN 的简单部署和管理以及安全。Outline 提供了强加密、用户管理工具、并支持多平台,包括 Windows, macOS, Linux, iOS, 和 Android。

Outline 主要由 2 部分组成:

  • Outline Manager : 用来部署 VPN 服务器,以及管理用户、限速等
  • Outline Client : 连接 VPN 的客户端,支持多平台

本文示例基本环境信息

  • Ubuntu 22.04.4 LTS (Jammy Jellyfish)
  • Outline Manager Version 1.15.2

Outline 环境 部署

Outline Manager 部署

Outline Manager 部署非常的简单,只需要下载可执行文件,添加可执行权限并启动即可

$ wget https://s3.amazonaws.com/outline-releases/manager/linux/stable/Outline-Manager.AppImage

$ chmod +x Outline-Manager.AppImage

$ ./Outline-Manager.AppImage
Outline Manager is starting
libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[42740:0925/174650.529715:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
Launching web app from outline://web_app/index.html?version=1.15.2&sentryDsn=https%3A%2F%2F9df8c810bf1b482d979da996e3e63c40%40o74047.ingest.sentry.io%2F215496
libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[42774:0925/174651.006194:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[42800:0925/174651.310808:ERROR:gpu_memory_buffer_support_x11.cc(44)] dri3 extension not supported.
Checking for update
Generated new staging user ID: c5db7469-3a5b-5365-a374-7e29a6e0c71a
Update for version 1.15.2 is not available (latest version: 1.15.2, downgrade is disallowed).

  • 为安全起见,Outline Manager 不支持以 root 用户执行,请以普通用户身份执行

  • Outline Manager 依赖于 fuse,执行命令 sudo apt install fuse 安装

  • Outline VPN Server 依赖于 Docker 和 curl,请提前安装

Outline Manager 运行后会启动 UI

Outline VPN Server 部署

Outline 环境中,VPN Server 负责具体的 VPN 节点实现。要部署 VPN Server,选择合适的服务器环境,比如使用自己的本地服务器则选择 Set up Outline anywhere,然后根据提示在具体的 VPN Server 上部署程序即可

  1. 根据提示,执行以下命令,部署 VPN Server 环境程序

    # sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh)"
    > Verifying that Docker is installed .......... OK
    > Verifying that Docker daemon is running ..... OK
    > Setting PUBLIC_HOSTNAME to external IP ...... OK
    > Creating persistent state dir ............... OK
    > Generating secret key ....................... OK
    > Generating TLS certificate .................. OK
    > Generating SHA-256 certificate fingerprint .. OK
    > Writing config .............................. OK
    > Starting Shadowbox .......................... OK
    > Starting Watchtower ......................... OK
    > Removing watchtower container ............... OK
    > Restarting watchtower ....................... OK
    > Waiting for Outline server to be healthy .... OK
    > Creating first user ......................... OK
    > Adding API URL to config .................... OK
    > Checking host firewall ...................... OK

    CONGRATULATIONS! Your Outline server is up and running.

    To manage your Outline server, please copy the following line (including curly
    brackets) into Step 2 of the Outline Manager interface:

    {"apiUrl":"https://66.26.90.25:50472/Q6XjXdbbVbetfAV0TK2cyw","certSha256":"67695819036A0FA4CE3C9E4AFAA0466D3C4BE4D9B04DBF7D8BA820FB379C0E4C"}

    If you have connection problems, it may be that your router or cloud provider
    blocks inbound connections, even though your machine seems to allow them.

    Make sure to open the following ports on your firewall, router or cloud provider:
    - Management port 50472, for TCP
    - Access key port 13279, for TCP and UDP

    根据提示 Management port 50472, for TCPAccess key port 13279, for TCP and UDP,防火墙放通对应的端口

    默认情况下,Management portAccess key port 使用随机端口,要使用自定义的固定端口,使用以下命令配置 VPN Server 环境

    bash install_server.sh --api-port 65530 --keys-port 65531

    如果在同一台主机上重复执行 install_server.sh,请删除持久化数据目录,默认为 /opt/outline/ ,否则可能出现重复部署后某些配置依然是旧的。

  2. 下载客户端程序,COPY ACCESS KEY 到客户端测试连接。

阅读全文 »

Certbot 是 Let’s Encrypt SSL 官方推荐的 ACME 协议客户端,它是一个 Python 程序,且包含模块化插件支持。Let’s Encrypt 的根证书浏览器支持广泛,且支持泛域名。但单个证书的有效期为 90 天,以防止滥用。

安装 Certbot

官方安装步骤参考

以下步骤演示在 Python3 环境中安装 Certbot 及其相关依赖

  1. 安装 certbot
    pip install certbot
  2. 申请证书时,要使用 DNS 方式验证域名所有权并且 DNS 使用 Cloudflare 的情况下,可以安装 certbot-dns-cloudflare 插件实现自动验证,参考以下命令安装 certbot-dns-cloudflare,此模块需要 cloudflare 模块的支持
    pip install cloudflare
    pip install certbot-dns-cloudflare
    安装完成后检查相关模块和版本。其中 cloudflare 版本需要最低为 2.3.1 [1]
    # pip list
    certbot 2.10.0
    certbot-dns-cloudflare 2.10.0
    cloudflare 2.19.2
    以上模块安装完成后,即可使用 certbot 申请域名证书,并支持 Cloudflare DNS 的自动验证。

基于 Cloudflare DNS 的自动验证申请域名证书

参考步骤安装 certbot 及 Cloudflare DNS 插件后 即可使用 certbot 自动请求 Cloudflare DNS 创建申请证书时需要的 DNS 记录自动完成域名归属权的验证过程。

certbot 支持的 Cloudflare 相关的参数如下

参数 说明 示例
--dns-cloudflare 使用 Cloudflare 的 DNS 插件自动验证域名归属权
--dns-cloudflare-credentials 请求 Cloudflare 的授权配置文件
--dns-cloudflare-propagation-seconds 请求 Cloudflare DNS 添加相关 DNS 记录后,让 ACME 服务等待多少秒再验证 DNS 记录。主要用来防止 DNS 记录添加后,缓存 DNS 服务器未来得及更新最新记录。
默认为 10

Cloudflare Credentials 说明

假设有 Cloudflare 账号的 Global API Key,则 Credentials 配置文件内容参考如下

cloudflare.ini
# Cloudflare API credentials used by Certbot
dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234

申请证书的具体命令如下,如果是第一次申请,需要根据提示填写自己的邮箱信息并同意许可协议,邮箱用于接受之后系统发送的错误或者域名证书过期等信息

certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
-d example.com \
-d www.example.com

如果是非交互式环境,可以使用参数 --email your-email@example.com--agree-tos 自动绑定邮箱并同意许可

阅读全文 »

Shadowsocks 官网简介

基于 Python3 环境的 Shadowsocks 部署

执行以下命令之一安装 Shadowsocks (Python3 版本)

pip3 install git+https://github.com/shadowsocks/shadowsocks.git@master

pip3 install shadowsocks

配置 Shadowsocks

创建一个配置文件,比如放在 /etc/shadowsocks/config.json 目录下。配置文件的内容如下:

{
"server": "0.0.0.0",
"server_port": 8388,
"local_address": "127.0.0.1",
"local_port": 1080,
"password": "your_password",
"timeout": 300,
"method": "aes-256-cfb",
"fast_open": false
}

配置选项说明

  • server : 服务器监听的 IP 地址,0.0.0.0 表示监听所有接口。
  • server_port : 服务器监听的端口,客户端连接到这个端口。
  • password : 用于加密流量的密码,请设置一个强密码。
  • method : 加密方法。其他加密算法请参考官网
  • timeout : 超时时间(秒)。
  • fast_open : 如果启用 TCP Fast Open,请将其设置为 true,但需要内核支持。

启动 Shadowsocks 服务

使用以下命令启动 Shadowsocks 服务,该命令会以后台进程的方式启动 Shadowsocks:

ssserver -c /etc/shadowsocks/config.json -d start

常用选项

选项 说明 示例
-h, --help 打印帮助信息
-d [start / stop / restart ] 以 Daemon 方式(后台)运行
--pid-file Daemon 模式启动时的 PID 文件路径
--log-file Daemon 模式启动时日志文件路径
--user 运行服务的用户
-v, -vv verbose 模式
-q, -qq quite 模式
-c 配置文件路径 ssserver -c /etc/shadowsocks/config.json -d start
-s 指定服务端监听地址,默认为 0.0.0.0 。等同于配置文件中的 server
-p 指定服务端监听端口,默认为 8388 。等同于配置文件中的 server_port
-k 指定密码 。等同于配置文件中的 password
-m 加密方法,默认为 aes-256-cfb 。 等同于配置文件中的 method
-t 超时时间(单位为 ),默认 300s 。 等同于配置文件中的 timeout
--fast-open 启用 TCP_FASTOPEN,需要 Linux 3.7+
--workers workers 数量,Linux/Unix 可用
--forbidden-ip , 分割的 IP 列表,在此列表中的 IP 禁止连接,即黑名单
--manager-address 服务端 UDP 管理地址

为 Shadowsocks 配置 systemd services 文件

参考以下内容,为 Shadowsocks 配置 systemd services 文件

/etc/systemd/system/shadowsocks.service
[Unit]
Description=Shadowsocks Proxy Server
After=network.target

[Service]
ExecStart=/usr/local/bin/ssserver -c /etc/shadowsocks/config.json
Restart=on-failure

[Install]
WantedBy=multi-user.target

启用并启动 Shadowsocks 服务

sudo systemctl enable shadowsocks
sudo systemctl start shadowsocks

客户端连接

在客户端(如 Windows、macOS、iOS 或 Android)上,使用 Shadowsocks 客户端进行连接。

客户端配置

  • 服务器地址 : 填写你服务器的公网 IP。
  • 服务器端口 :填写 config.json 中的 server_port,如 8388
  • 密码 : 填写配置文件中的 password
  • 加密方法 : 选择 method 中配置的加密方法,如 aes-256-cfb

如果需要调试或查看运行日志,可以通过以下命令查看 Shadowsocks 的日志:

journalctl -u shadowsocks

ss 命令是一个查看 Linux 系统 socket 统计信息的工具,类似于 netstat,但是能显示更多的 TCP 和状态信息。

常用选项 ,可查看 man ss

选项 说明 示例
-h, --help 输出选项的简要说明
-V, --version 打印版本信息
-H, --no-header 不打印首行(Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
-n, --numeric 不对服务名进行解析,直接输出端口(数值类型)
-r, --resolve 尝试解析 IP 和 端口 为对应的名称,默认行为
-a, --all 列出正在监听的端口以及已经建立连接的端口
-l, --listening 仅列出正在监听的端口,默认不列出。
-m, --memory 显示 socket内存 使用情况
-p, --processes 显示使用此 socket 的进程
-s, --summary 显示简略的统计信息
-4, --ipv4 只显示 IPv4 相关的 socket
-6, --ipv6 只显示 IPv6 相关的 socket
-t, --tcp 只显示 TCP 相关 socket
-u, --udp 只显示 UDP 相关 socket

环境信息

  • Centos 7

automake

编译安装软件报错

error: require Automake 1.14, but have 1.13.4

Automake 版本不匹配,需要安装 Automake 1.14

$ rpm -qa | grep automake
automake-1.13.4-3.el7.noarch

以下步骤安装 automake-1.14.1

wget http://ftp.gnu.org/gnu/automake/automake-1.14.1.tar.gz
tar -xf automake-1.14.1.tar.gz
cd automake-1.14.1
./bootstrap.sh

以上步骤执行完成后,会生成 configure 可执行文件

./configure
make
make install

安装完成后,执行以下命令验证版本

$ automake --version
automake (GNU automake) 1.14.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Tom Tromey <tromey@redhat.com>
and Alexandre Duret-Lutz <adl@gnu.org>.

makeinfo

编译安装软件报错

makeinfo: command not found

makeinfo 命令不存在,执行以下命令安装

yum install texinfo

gcc

no acceptable C compiler found in $PATH

缺少 gcc 编译器,安装即可

yum install -y gcc

A compiler with support for C++11 language features is required

编译安装软件时报错

configure: error: *** A compiler with support for C++11 language features is required.

错误原因为 gcc 版本太低。查看当前 gcc 版本

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)

安装 gcc-8.3.0

以下步骤演示安装 gcc-8.3.0 [1]

  1. 下载安装包,官方下载地址
    wget ftp://ftp.irisa.fr/pub/mirrors/gcc.gnu.org/gcc/releases/gcc-8.3.0/gcc-8.3.0.tar.gz
    tar -xf gcc-8.3.0.tar.gz
    cd gcc-8.3.0
  2. 编译安装。编译依赖 GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+,需要先按照顺序安装这 3 个依赖。依赖安装参考: 安装 GMP安装 MPFR安装 MPC
    $ ./configure --prefix=/usr/local/gcc-8.3.0 --disable-multilib
    $ make
    $ make install
  3. 安装完成后,需要更新系统标准库 查看当前系统使用的 gcc 库文件,可以看到版本为 libstdc++.so.6.0.19
    $ ls /usr/lib64/libstdc++.so.6
    libstdc++.so.6 libstdc++.so.6.0.19

    $ ls /usr/lib64/libstdc++.so.6 -l
    lrwxrwxrwx 1 root root 19 May 30 08:05 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
    执行以下操作,更新 libstdc++.so.6 到最新安装的版本
    $ rm -rf /usr/lib64/libstdc++.so.6

    $ ln -s /usr/local/gcc-8.3.0/lib64/libstdc++.so.6.0.25 /usr/lib64/libstdc++.so.6

    $ ls /usr/lib64/libstdc++.so.6 -l
    lrwxrwxrwx 1 root root 46 Jun 9 09:31 /usr/lib64/libstdc++.so.6 -> /usr/local/gcc-8.3.0/lib64/libstdc++.so.6.0.25

安装 GMP

安装包下载地址

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
tar -jxvf gmp-6.1.0.tar.bz2
cd gmp-6.1.0
./configure
make && make install

安装 MPFR

安装包下载地址

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
tar -jxvf mpfr-3.1.4.tar.bz2
cd mpfr-3.1.4
./configure
make && make install

安装 MPC

安装包下载地址

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
tar -zxvf mpc-1.0.3.tar.gz
cd mpc-1.0.3
./configure
make && make install
阅读全文 »

环境信息

  • Ubuntu 24.04.1 LTS (Noble Numbat)
  • nftables v1.0.9 (Old Doc Yak #3)

配置错误

Statement after terminal statement has no effect

有以下配置:

ip daddr 127.0.0.11 jump DOCKER_OUTPUT counter;

meta l4proto tcp ip daddr 127.0.0.11 tcp dport 53 dnat to 127.0.0.11:45143 counter;

加载配置时报错: Error: Statement after terminal statement has no effect

错误原因nftables 规则中在 终止语句(terminal statement(如 jumpdnat)后添加的语句(如 counter)没有作用,因为 jumpdnat 语句已经处理了数据包,不会再执行后续的语句。

nftables 中,终止语句(terminal statement 是那些一旦执行后就结束了该数据包的处理,例如 jumpacceptdropdnatsnat 等。因为这些语句会决定数据包的最终去向,所以在这些语句后面再添加如 counter 这样的语句是无效的。

解决方法 : 要正确配置计数器,你需要 counter 放在终止语句 之前,这样在执行 jumpdnat 之前,数据包会先经过计数器。

ip daddr 127.0.0.11 counter jump DOCKER_OUTPUT;

meta l4proto tcp ip daddr 127.0.0.11 tcp dport 53 counter dnat to 127.0.0.11:45143;

syntax error

一次性配置多个端口

假如要在一个规则中同时放通 HTTP 和 HTTPS (80443 端口),以下是错误语句

# nft insert inet filter input handle 11 tcp dport 80,443 counter accept comment \"for nginx\"
Error: syntax error, unexpected inet, expecting rule
insert inet filter input handle 11 tcp dport 80,443 counter accept comment for nginx
^^^^

nftables 中,多个端口 在指定时不能直接用逗号分隔。对于多个端口,应该使用集合({})的语法来指定。以下为正确语法

# nft insert rule inet filter input handle 11 tcp dport { 80,443 } counter accept comment \"for nginx\"

注意: 使用 集合{})语法时要注意其中的空格,{ 80,443 } 是正确格式,如果写成 {80,443} 则是错误格式

cmd 中添加注释报错

使用以下语句添加规则报错:

# nft insert rule inet filter input handle 11 tcp dport { 80,443 } counter accept comment "for nginx" 
Error: syntax error, unexpected string, expecting end of file or newline or semicolon
insert rule inet filter input handle 11 tcp dport { 80,443 } counter accept comment for nginx
^^^^^

正确格式如下:

# nft insert rule inet filter input handle 11 tcp dport { 80,443 } counter accept comment \"for nginx\"

注意: 在 cmd 中交互式操作时,注释中使用的 双引号("" 要使用 转义(\

阅读全文 »

环境信息

  • Centos 7.9.2009
  • docker-ce-19.03.15

Docker 网络模式

Bridge 模式

bridge 模式是 docker 的默认网络模式,不使用 --network 参数,就是 bridge 模式。

当 Docker 进程启动时,会在主机上创建一个名为 docker0 的虚拟网桥,默认主机上启动的 Docker 容器会连接到这个虚拟网桥上。

容器启动时,docker 会从 docker0 网桥的子网中分配一个 IP 地址给容器中的网卡。大体流程为在主机上创建一个 `veth pair`,Docker 将 veth pair 的一端放在容器中,命名为 eth0 并配置 IP,网关,路由等信息,将 veth pair 的另一端加入 docker0 网桥。

通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。

Host 模式

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机一样在 Root Network Namespace,容器中看到的网络方面的信息和宿主机一样,容器使用的网络资源在整个 Root Network Namespace 不能出现冲突。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口,主机名也是使用宿主机的。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

host 模式下的容器可以看到宿主机上的所有网卡信息,可以直接使用宿主机 IP 或主机名与外界通信,无需额外的 NAT,也无需通过 Linux bridge 进行转发或者数据包的封装,可以访问主机上的其他任一容器

使用如下命令参数启动 host 网络模式的容器

docker run --network host --name test1 -p 80:80 -d -it centos:centos7.9.2009

host 模式的容器,没有自己的 network namespace,在 root network namespace 中。进入测试容器 test1,查看网卡、 IP 信息及端口、主机名信息,会看到和宿主机一样的信息。

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:e7:c0:27 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:f2:1b:dc:ea brd ff:ff:ff:ff:ff:ff

$ ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:e7:c0:27 brd ff:ff:ff:ff:ff:ff
inet 192.168.142.10/24 brd 192.168.142.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fee7:c027/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:f2:1b:dc:ea brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever

$ [root@test1 /]# netstat -anutp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 124/nginx: master p
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 36 192.168.142.10:22 192.168.142.1:61396 ESTABLISHED -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::81 :::* LISTEN 124/nginx: master p
tcp6 0 0 :::22 :::* LISTEN -

host 模式的缺点

  • 容器没有自己的 network namespace ,网络和宿主机或其他使用 host 模式的容器未隔离,容易出现资源冲突,比如同一个宿主机上,使用 host 模式的容器中启动的端口不能相同。

None 模式

使用 none 模式,Docker 容器拥有自己的 Network Namespace,但是,系统并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡(lo 回环网卡除外)、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。

参考以下命令创建 none 模式的容器

docker run --network none --name test-none -p 82:80 -d -it centos7:my

容器创建后,进入容器中,查看网卡和 IP 等信息,容器中默认只存在 lo 网卡,不存在其他网卡

$ ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

以下操作演示手动为容器配置网络

  1. 创建 veth pair

    ip link add veth0 type veth peer name veth0_p
  2. veth pair 的一端 veth0 放入 docker 默认的网桥 docker0,另一端 veth0_p 放入容器中

    首先使用命令 docker inspect test-none | grep "Pid" 找到容器对应的 PID,此处为 84040,根据此 PID 将 veth 的一端放入容器的 network namespace 中

    ip link set dev veth0 master docker0

    ip link set dev veth0 up

    ip link set veth0_p netns 84040

    在宿主机上面检查 veth0,确定其已经加入网桥 docker0,并且 veth0_p 已不在 root network namespace

    $ ip link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:e7:c0:27 brd ff:ff:ff:ff:ff:ff
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
    link/ether 02:42:f2:1b:dc:ea brd ff:ff:ff:ff:ff:ff
    12: veth0@if11: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master docker0 state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether 16:7f:98:d8:9d:dc brd ff:ff:ff:ff:ff:ff link-netnsid 0

    重新进入容器,检查网卡信息,可以看到容器中已经有了网卡 veth0_p,状态为 DOWN

    $ ip -d link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    11: veth0_p@if12: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether be:f1:94:9f:b8:c9 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
    veth addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
  3. 为容器中的网卡配置 IP 及网关等信息

    为了能在宿主机对容器的 network namespace 进行操作,首先需要将容器的 network namespace 暴露出来,之后可以在宿主机通过 network namespace 名称(此处为 84040,可以自定义)操作 network namespaceLinux network namespace 参考

    $ ln -s /proc/84040/ns/net /var/run/netns/84040
    $ ip netns ls
    84040 (id: 0)

    通过 network namespace 名称(此处为 84040)配置容器中网卡的 IP 地址信息

    ip netns exec 84040 ip link set dev veth0_p name eth0
    ip netns exec 84040 ip link set dev eth0 up

    ip netns exec 84040 ip add add 172.17.0.10/16 dev eth0

    ip netns exec 84040 ip route add default via 172.17.0.1

    进入容器检查网络信息

    $ ip add
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7e:36:b3:20:a1:8c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.10/16 scope global eth0
    valid_lft forever preferred_lft forever

    $ ip route show
    default via 172.17.0.1 dev eth0
    172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.10

    进入容器测试网络连接

    $ ping 8.8.8.8
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=127 time=37.4 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=127 time=37.0 ms
    ^C
    --- 8.8.8.8 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1000ms
    rtt min/avg/max/mdev = 37.047/37.234/37.422/0.269 ms
阅读全文 »