OpenStack Yoga版安装笔记(十七)安全组笔记

一、安全组与iptables的关系

OpenStack的安全组(Security Group)默认是通过Linux的iptables实现的。以下是其主要实现原理和机制:

  1. 安全组与iptables的关系

    OpenStack的安全组规则通过iptables的规则链实现。每条安全组规则会被转换为相应的iptables规则,这些规则会动态生成并应用到计算节点的iptables中。

  2. 规则链的生成

    安全组规则会根据虚拟机的网络接口(如虚拟机网卡)生成特定的iptables规则链。

二、回顾"启动一个实例"中的内容

《OpenStack Yoga版安装笔记(十四)启动一个实例》中,执行了以下命令:

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1、创建network | root@osclient ~(admin/amdin)# openstack network create --share --external --provider-physical-network provider --provider-network-type flat provider |
| 2、创建subnet | root@osclient ~(admin/amdin)# openstack subnet create --network provider --allocation-pool start=203.0.113.101,end=203.0.113.250 --dns-nameserver 8.8.4.4 --gateway 203.0.113.1 --subnet-range 203.0.113.0/24 provider |
| 3、创建一个新的计算实例类型(flavor) | root@osclient ~(admin/amdin)# openstack flavor create --id 0 --vcpus 1 --ram 64 --disk 1 m1.nano |
| 4、user "myuser"登录到project "myproject" | root@osclient:~# cat demo-openrc export OS_PROJECT_DOMAIN_NAME=Default export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_NAME=myproject export OS_USERNAME=myuser export OS_PASSWORD=openstack export OS_AUTH_URL=http://controller:5000/v3 export OS_IDENTITY_API_VERSION=3 export OS_IMAGE_API_VERSION=2 export PS1='\u@\h \W(myproject/myuser)\$ ' root@osclient:~# source demo-openrc root@osclient ~(myproject/myuser)# pwd /root root@osclient ~(myproject/myuser)# |
| 5、生成一个 SSH 密钥对(公钥和私钥) | root@osclient ~(myproject/myuser)# ssh-keygen -q -N "" Enter file in which to save the key (/root/.ssh/id_rsa): root@osclient ~(myproject/myuser)# ls .ssh authorized_keys id_rsa id_rsa.pub known_hosts 注:id_rsa,私钥;id_rsa.pub,公钥。 |
| 6、用户myuser使用 OpenStack CLI 将公钥上传到项目 myproject 中 | root@osclient ~(myproject/myuser)# openstack keypair create --public-key ~/.ssh/id_rsa.pub mykey |
| 7、列出当前项目中所有已注册的 SSH 密钥对 | root@osclient ~(myproject/myuser)# openstack keypair list |
| 8、在project myporject中,为默认的安全组(default)添加一条允许 ICMP 流量的入向规则(缺省为入向) | root@osclient ~(myproject/myuser)# openstack security group rule create --proto icmp default |
| 9、在project myporject中,为默认的安全组(default)添加一条允许所有来源的 TCP 流量访问 22 端口(SSH)的入向规则(缺省为入向) | root@osclient ~(myproject/myuser)# openstack security group rule create --proto tcp --dst-port 22 default |
| 10、列出当前项目中所有安全组的规则 | root@osclient ~(myproject/myuser)# openstack security group rule list |
| 11、在 OpenStack 中创建一个新的云实例。通过指定 flavor、镜像、网络、安全组和 SSH 密钥对,可以配置实例的资源和访问权限。确保所有指定的资源(如 flavor、镜像、网络和密钥对)在当前项目中可用,并验证实例的状态以确保其正常运行。 可以使用之前产生的私钥(id_rsa)通过SSH登录到云实例: ssh -i ~/.ssh/id_rsa <username>@<instance_ip> | root@osclient ~(myproject/myuser)# openstack server create --flavor m1.nano --image cirros --nic net-id=48f2b88e-7740-4d94-a631-69e2abadf25b --security-group default --key-name mykey provider-instance |

三、创建虚机后的网络拓扑

创建虚机后,Openstack视角的抽象网络拓扑:

实际的网络拓扑,其中openstack创建了qdhcpxxxx、brqxxxx、provider-instance:
实际网络拓扑示意

另外,本次环境中,还有一台运行openstack client的虚机(ip address: 10.0.20.100):

复制代码
root@osclient:~# ip a
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 fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ff:20:81 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 10.0.20.100/24 brd 10.0.20.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feff:2081/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:44:6b:2d:6a 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@osclient:~# ls
admin-openrc  demo-openrc  myproject-admin-openrc
root@osclient:~# 

四、查看虚机运行所在的主机

1、普通role的user无法查看虚机所在的主机信息

user "myuser" 在project "myproject"中赋予role "myrole",这是普通权限。

复制代码
root@osclient ~(admin/amdin)# source demo-openrc 
root@osclient ~(myproject/myuser)# cat demo-openrc 
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=myproject
export OS_USERNAME=myuser
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='\u@\h \W(myproject/myuser)\$ '
root@osclient ~(myproject/myuser)# openstack server list
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| ID                                   | Name              | Status  | Networks               | Image  | Flavor  |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| d2e4bc39-63c8-4c80-b33f-52f4e1891f50 | provider-instance | SHUTOFF | provider=203.0.113.125 | cirros | m1.nano |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
root@osclient ~(myproject/myuser)# openstack server show d2e4bc39-63c8-4c80-b33f-52f4e1891f50 
+-----------------------------+----------------------------------------------------------+
| Field                       | Value                                                    |
+-----------------------------+----------------------------------------------------------+
| OS-DCF:diskConfig           | MANUAL                                                   |
| OS-EXT-AZ:availability_zone | nova                                                     |
| OS-EXT-STS:power_state      | Shutdown                                                 |
| OS-EXT-STS:task_state       | None                                                     |
| OS-EXT-STS:vm_state         | stopped                                                  |
| OS-SRV-USG:launched_at      | 2024-09-28T03:28:51.000000                               |
| OS-SRV-USG:terminated_at    | None                                                     |
| accessIPv4                  |                                                          |
| accessIPv6                  |                                                          |
| addresses                   | provider=203.0.113.125                                   |
| config_drive                |                                                          |
| created                     | 2024-09-28T02:49:20Z                                     |
| flavor                      | m1.nano (0)                                              |
| hostId                      | 892d1a79d804f6b0fbfb68938ec0df8a0abc8e3d52660529538123e4 |
| id                          | d2e4bc39-63c8-4c80-b33f-52f4e1891f50                     |
| image                       | cirros (429decdd-9230-49c0-b735-70364c226eb5)            |
| key_name                    | mykey                                                    |
| name                        | provider-instance                                        |
| project_id                  | f5e75a3f7cc347ad89d20dcfe70dae01                         |
| properties                  |                                                          |
| security_groups             | name='default'                                           |
| status                      | SHUTOFF                                                  |
| updated                     | 2025-03-28T22:36:21Z                                     |
| user_id                     | 9382b59561c04dd1abf0a4cb7a8252ec                         |
| volumes_attached            |                                                          |
+-----------------------------+----------------------------------------------------------+
root@osclient ~(myproject/myuser)#

2、"admin" role的用户可以查看虚机所在主机的信息

google关键字搜索"openstack server show hostId",查看到类似的问题和解决办法:

Question #246423 "host-ids and extended server attributes" : Questions : OpenStack Compute (nova)

将user"admin"在project "myproject" 中赋予"admin" role:

复制代码
root@osclient ~(myproject/amdin)# source admin-openrc 
root@osclient ~(admin/amdin)# openstack role list
+----------------------------------+----------+
| ID                               | Name     |
+----------------------------------+----------+
| 17552c9a365d4944a50fd8ac271791c6 | member   |
| 48fa6b74f7b74d8698fe20b21ae8a02b | testrole |
| 83144b48ff1b4c54bb21d1fcb15921b5 | myrole   |
| be23525c20c44f05b3ba071455522fcb | reader   |
| e434c66b7af647158bcaa77686ca6e93 | admin    |
+----------------------------------+----------+
root@osclient ~(admin/amdin)# openstack role add --project myproject --user admin admin
root@osclient ~(admin/amdin)#

使用admin role的user可以查看虚机所在的主机信息,根据输出结果,这台虚机运行在host "compute1":

复制代码
root@osclient ~(myproject/myuser)# source myproject-admin-openrc 
root@osclient ~(myproject/admin)# cat myproject-admin-openrc 
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=myproject
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='\u@\h \W(myproject/admin)\$ '
root@osclient ~(myproject/admin)# openstack server list
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| ID                                   | Name              | Status  | Networks               | Image  | Flavor  |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| d2e4bc39-63c8-4c80-b33f-52f4e1891f50 | provider-instance | SHUTOFF | provider=203.0.113.125 | cirros | m1.nano |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
root@osclient ~(myproject/admin)# openstack server show d2e4bc39-63c8-4c80-b33f-52f4e1891f50
+-------------------------------------+----------------------------------------------------------+
| Field                               | Value                                                    |
+-------------------------------------+----------------------------------------------------------+
| OS-DCF:diskConfig                   | MANUAL                                                   |
| OS-EXT-AZ:availability_zone         | nova                                                     |
| OS-EXT-SRV-ATTR:host                | compute1                                                 |
| OS-EXT-SRV-ATTR:hypervisor_hostname | compute1                                                 |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000004                                        |
| OS-EXT-STS:power_state              | Shutdown                                                 |
| OS-EXT-STS:task_state               | None                                                     |
| OS-EXT-STS:vm_state                 | stopped                                                  |
| OS-SRV-USG:launched_at              | 2024-09-28T03:28:51.000000                               |
| OS-SRV-USG:terminated_at            | None                                                     |
| accessIPv4                          |                                                          |
| accessIPv6                          |                                                          |
| addresses                           | provider=203.0.113.125                                   |
| config_drive                        |                                                          |
| created                             | 2024-09-28T02:49:20Z                                     |
| flavor                              | m1.nano (0)                                              |
| hostId                              | 892d1a79d804f6b0fbfb68938ec0df8a0abc8e3d52660529538123e4 |
| id                                  | d2e4bc39-63c8-4c80-b33f-52f4e1891f50                     |
| image                               | cirros (429decdd-9230-49c0-b735-70364c226eb5)            |
| key_name                            | mykey                                                    |
| name                                | provider-instance                                        |
| project_id                          | f5e75a3f7cc347ad89d20dcfe70dae01                         |
| properties                          |                                                          |
| security_groups                     | name='default'                                           |
| status                              | SHUTOFF                                                  |
| updated                             | 2025-03-28T22:36:21Z                                     |
| user_id                             | 9382b59561c04dd1abf0a4cb7a8252ec                         |
| volumes_attached                    |                                                          |
+-------------------------------------+----------------------------------------------------------+
root@osclient ~(myproject/admin)# 
字段
OS-EXT-AZ:availability_zone nova
OS-EXT-SRV-ATTR:host compute1
OS-EXT-SRV-ATTR:hypervisor_hostname compute1

信息解读:

  1. availability_zone: nova

    • 实例部署在默认的可用区(Availability Zone)nova中。

    • OpenStack中,nova是默认的可用区名称,表示实例运行在未特别配置的区域。

  2. host: compute1

    • 实例当前运行在名为compute1的计算节点(Compute Node)上。

    • 这是物理主机的名称,负责承载虚拟机实例。

  3. hypervisor_hostname: compute1

    • 该计算节点的虚拟化平台(如KVM、Xen)的主机名也是compute1

    • 通常与host字段一致,表示实例运行在同一个物理节点上。

五、虚机关闭状态时查看iptables

1、查看虚机处于关闭状态

复制代码
root@osclient ~(myproject/admin)# source demo-openrc 
root@osclient ~(myproject/myuser)# cat demo-openrc 
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=myproject
export OS_USERNAME=myuser
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='\u@\h \W(myproject/myuser)\$ '
root@osclient ~(myproject/myuser)# openstack server list
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| ID                                   | Name              | Status  | Networks               | Image  | Flavor  |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| d2e4bc39-63c8-4c80-b33f-52f4e1891f50 | provider-instance | SHUTOFF | provider=203.0.113.125 | cirros | m1.nano |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
root@osclient ~(myproject/myuser)# 

2、 此时虚拟网络环境

复制代码
root@compute1:~# virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes

root@compute1:~# brctl show
bridge name     bridge id               STP enabled     interfaces
brq48f2b88e-77          8000.ea99122ddd99       no
virbr0          8000.525400db7049       yes
root@compute1:~# 

3、查看iptables

查看"provider-instance"虚机运行所在的主机compute1的iptables,由于虚机关闭,此时OpenStack Neutron没有为该虚机添加相应规则。

复制代码
root@compute1:~# iptables-save
# Generated by iptables-save v1.8.7 on Sun Mar 30 05:56:29 2025
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Sun Mar 30 05:56:29 2025
# Generated by iptables-save v1.8.7 on Sun Mar 30 05:56:29 2025
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LIBVIRT_FWI - [0:0]
:LIBVIRT_FWO - [0:0]
:LIBVIRT_FWX - [0:0]
:LIBVIRT_INP - [0:0]
:LIBVIRT_OUT - [0:0]
-A INPUT -j LIBVIRT_INP
-A FORWARD -j LIBVIRT_FWX
-A FORWARD -j LIBVIRT_FWI
-A FORWARD -j LIBVIRT_FWO
-A OUTPUT -j LIBVIRT_OUT
-A LIBVIRT_FWI -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A LIBVIRT_FWI -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWO -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A LIBVIRT_FWO -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWX -i virbr0 -o virbr0 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 68 -j ACCEPT
COMMIT
# Completed on Sun Mar 30 05:56:29 2025
# Generated by iptables-save v1.8.7 on Sun Mar 30 05:56:29 2025
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
COMMIT
# Completed on Sun Mar 30 05:56:29 2025
root@compute1:~# 

root@compute1:~# iptables -t filter -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
13804 3614K LIBVIRT_INP  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 LIBVIRT_FWX  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWI  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWO  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
12954 4090K LIBVIRT_OUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
    0     0 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain LIBVIRT_FWO (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 *       192.168.122.0/24     0.0.0.0/0           
    0     0 REJECT     all  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain LIBVIRT_FWX (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 virbr0  0.0.0.0/0            0.0.0.0/0           

Chain LIBVIRT_INP (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67

Chain LIBVIRT_OUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:68
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:68
root@compute1:~# 

LIBVIRT_FWI、LIBVIRT_FWO、LIBVIRT_FWX、LIBVIRT_INP、LIBVIRT_OUT是Libvirt在管理虚拟机网络时创建的iptables规则链,可参考<Ubuntu22.04 KVM安装笔记>相关内容。

这些链表不属于Openstack Neutron管理。

六、虚机开启时查看iptables

1、开启虚机

复制代码
root@osclient ~(myproject/myuser)# openstack server list
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| ID                                   | Name              | Status  | Networks               | Image  | Flavor  |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
| d2e4bc39-63c8-4c80-b33f-52f4e1891f50 | provider-instance | SHUTOFF | provider=203.0.113.125 | cirros | m1.nano |
+--------------------------------------+-------------------+---------+------------------------+--------+---------+
root@osclient ~(myproject/myuser)# openstack server start provider-instance
root@osclient ~(myproject/myuser)# openstack server list
+--------------------------------------+-------------------+--------+------------------------+--------+---------+
| ID                                   | Name              | Status | Networks               | Image  | Flavor  |
+--------------------------------------+-------------------+--------+------------------------+--------+---------+
| d2e4bc39-63c8-4c80-b33f-52f4e1891f50 | provider-instance | ACTIVE | provider=203.0.113.125 | cirros | m1.nano |
+--------------------------------------+-------------------+--------+------------------------+--------+---------+
root@osclient ~(myproject/myuser)# 
root@osclient ~(myproject/myuser)# 

2、此时虚拟网络环境

复制代码
root@compute1:~# virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes

root@compute1:~# brctl show
bridge name     bridge id               STP enabled     interfaces
brq48f2b88e-77          8000.ea99122ddd99       no              ens35
                                                        tap2d863922-bc
virbr0          8000.525400db7049       yes
root@compute1:~# 
root@compute1:~# ip a
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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:51:16:68 brd ff:ff:ff:ff:ff:ff
    altname enp2s0
    inet 10.0.20.12/24 brd 10.0.20.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe51:1668/64 scope link 
       valid_lft forever preferred_lft forever
3: ens35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master brq48f2b88e-77 state UP group default qlen 1000
    link/ether 00:0c:29:51:16:72 brd ff:ff:ff:ff:ff:ff
    altname enp2s3
    inet6 fe80::20c:29ff:fe51:1672/64 scope link 
       valid_lft forever preferred_lft forever
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:db:70:49 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
5: brq48f2b88e-77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ea:99:12:2d:dd:99 brd ff:ff:ff:ff:ff:ff
6: tap2d863922-bc: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master brq48f2b88e-77 state UNKNOWN group default qlen 1000
    link/ether fe:16:3e:60:78:cd brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc16:3eff:fe60:78cd/64 scope link 
       valid_lft forever preferred_lft forever
root@compute1:~# 

3、查看iptables-save

开启虚机后,OpenStack Neutron根据安全组配置,在iptables中为该虚机插入相应的安全组规则。

复制代码
root@compute1:~# iptables-save
# Generated by iptables-save v1.8.7 on Sun Mar 30 06:11:29 2025
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Sun Mar 30 06:11:29 2025
# Generated by iptables-save v1.8.7 on Sun Mar 30 06:11:29 2025
*raw
:PREROUTING ACCEPT [1116:236588]
:OUTPUT ACCEPT [853:288723]
:neutron-linuxbri-OUTPUT - [0:0]
:neutron-linuxbri-PREROUTING - [0:0]
-A PREROUTING -j neutron-linuxbri-PREROUTING
-A OUTPUT -j neutron-linuxbri-OUTPUT
-A neutron-linuxbri-PREROUTING -m physdev --physdev-in brq48f2b88e-77 -m comment --comment "Set zone for d863922-bc" -j CT --zone 4097
-A neutron-linuxbri-PREROUTING -i brq48f2b88e-77 -m comment --comment "Set zone for d863922-bc" -j CT --zone 4097
-A neutron-linuxbri-PREROUTING -m physdev --physdev-in tap2d863922-bc -m comment --comment "Set zone for d863922-bc" -j CT --zone 4097
COMMIT
# Completed on Sun Mar 30 06:11:29 2025
# Generated by iptables-save v1.8.7 on Sun Mar 30 06:11:29 2025
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LIBVIRT_FWI - [0:0]
:LIBVIRT_FWO - [0:0]
:LIBVIRT_FWX - [0:0]
:LIBVIRT_INP - [0:0]
:LIBVIRT_OUT - [0:0]
:neutron-filter-top - [0:0]
:neutron-linuxbri-FORWARD - [0:0]
:neutron-linuxbri-INPUT - [0:0]
:neutron-linuxbri-OUTPUT - [0:0]
:neutron-linuxbri-i2d863922-b - [0:0]
:neutron-linuxbri-local - [0:0]
:neutron-linuxbri-o2d863922-b - [0:0]
:neutron-linuxbri-s2d863922-b - [0:0]
:neutron-linuxbri-sg-chain - [0:0]
:neutron-linuxbri-sg-fallback - [0:0]
-A INPUT -j neutron-linuxbri-INPUT
-A INPUT -j LIBVIRT_INP
-A FORWARD -j neutron-filter-top
-A FORWARD -j neutron-linuxbri-FORWARD
-A FORWARD -j LIBVIRT_FWX
-A FORWARD -j LIBVIRT_FWI
-A FORWARD -j LIBVIRT_FWO
-A OUTPUT -j neutron-filter-top
-A OUTPUT -j neutron-linuxbri-OUTPUT
-A OUTPUT -j LIBVIRT_OUT
-A LIBVIRT_FWI -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A LIBVIRT_FWI -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWO -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A LIBVIRT_FWO -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A LIBVIRT_FWX -i virbr0 -o virbr0 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A LIBVIRT_INP -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 68 -j ACCEPT
-A neutron-filter-top -j neutron-linuxbri-local
-A neutron-linuxbri-FORWARD -m physdev --physdev-out tap2d863922-bc --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-linuxbri-sg-chain
-A neutron-linuxbri-FORWARD -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-linuxbri-sg-chain
-A neutron-linuxbri-INPUT -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Direct incoming traffic from VM to the security group chain." -j neutron-linuxbri-o2d863922-b
-A neutron-linuxbri-i2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN
-A neutron-linuxbri-i2d863922-b -d 203.0.113.125/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-linuxbri-i2d863922-b -d 255.255.255.255/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-linuxbri-i2d863922-b -m set --match-set NIPv415dfe688-d6fc-4231-a670- src -j RETURN
-A neutron-linuxbri-i2d863922-b -p icmp -j RETURN
-A neutron-linuxbri-i2d863922-b -p tcp -m tcp --dport 22 -j RETURN
-A neutron-linuxbri-i2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP
-A neutron-linuxbri-i2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback
-A neutron-linuxbri-o2d863922-b -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN
-A neutron-linuxbri-o2d863922-b -j neutron-linuxbri-s2d863922-b
-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN
-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 67 --dport 68 -m comment --comment "Prevent DHCP Spoofing by VM." -j DROP
-A neutron-linuxbri-o2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN
-A neutron-linuxbri-o2d863922-b -j RETURN
-A neutron-linuxbri-o2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP
-A neutron-linuxbri-o2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback
-A neutron-linuxbri-s2d863922-b -s 203.0.113.125/32 -m mac --mac-source fa:16:3e:60:78:cd -m comment --comment "Allow traffic from defined IP/MAC pairs." -j RETURN
-A neutron-linuxbri-s2d863922-b -m comment --comment "Drop traffic without an IP/MAC allow rule." -j DROP
-A neutron-linuxbri-sg-chain -m physdev --physdev-out tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-i2d863922-b
-A neutron-linuxbri-sg-chain -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-o2d863922-b
-A neutron-linuxbri-sg-chain -j ACCEPT
-A neutron-linuxbri-sg-fallback -m comment --comment "Default drop rule for unmatched traffic." -j DROP
COMMIT
# Completed on Sun Mar 30 06:11:29 2025
# Generated by iptables-save v1.8.7 on Sun Mar 30 06:11:29 2025
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
COMMIT
# Completed on Sun Mar 30 06:11:29 2025
root@compute1:~# 

root@compute1:~# iptables -t filter -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
77331  147M neutron-linuxbri-INPUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
92507  151M LIBVIRT_INP  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 4387  679K neutron-filter-top  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 4387  679K neutron-linuxbri-FORWARD  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWX  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWI  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWO  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
73417   18M neutron-filter-top  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
73417   18M neutron-linuxbri-OUTPUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
87631   23M LIBVIRT_OUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
    0     0 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain LIBVIRT_FWO (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 *       192.168.122.0/24     0.0.0.0/0           
    0     0 REJECT     all  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain LIBVIRT_FWX (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 virbr0  0.0.0.0/0            0.0.0.0/0           

Chain LIBVIRT_INP (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67

Chain LIBVIRT_OUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:68
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:68

Chain neutron-filter-top (2 references)
 pkts bytes target     prot opt in     out     source               destination         
77804   19M neutron-linuxbri-local  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain neutron-linuxbri-FORWARD (1 references)
 pkts bytes target     prot opt in     out     source               destination         
 4122  641K neutron-linuxbri-sg-chain  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-out tap2d863922-bc --physdev-is-bridged /* Direct traffic from the VM interface to the security group chain. */
  265 37986 neutron-linuxbri-sg-chain  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in tap2d863922-bc --physdev-is-bridged /* Direct traffic from the VM interface to the security group chain. */

Chain neutron-linuxbri-INPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 neutron-linuxbri-o2d863922-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in tap2d863922-bc --physdev-is-bridged /* Direct incoming traffic from VM to the security group chain. */

Chain neutron-linuxbri-OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain neutron-linuxbri-i2d863922-b (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  245 22997 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED /* Direct packets associated with a known session to the RETURN chain. */
    2   732 RETURN     udp  --  *      *       0.0.0.0/0            203.0.113.125        udp spt:67 dpt:68
    0     0 RETURN     udp  --  *      *       0.0.0.0/0            255.255.255.255      udp spt:67 dpt:68
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set NIPv415dfe688-d6fc-4231-a670- src
    1    60 RETURN     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    2   104 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID /* Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack. */
 3872  617K neutron-linuxbri-sg-fallback  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Send unmatched traffic to the fallback chain. */

Chain neutron-linuxbri-local (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain neutron-linuxbri-o2d863922-b (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   670 RETURN     udp  --  *      *       0.0.0.0              255.255.255.255      udp spt:68 dpt:67 /* Allow DHCP client traffic. */
  263 37316 neutron-linuxbri-s2d863922-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 RETURN     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:68 dpt:67 /* Allow DHCP client traffic. */
    0     0 DROP       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:67 dpt:68 /* Prevent DHCP Spoofing by VM. */
  246 36272 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED /* Direct packets associated with a known session to the RETURN chain. */
   17  1044 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID /* Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack. */
    0     0 neutron-linuxbri-sg-fallback  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Send unmatched traffic to the fallback chain. */

Chain neutron-linuxbri-s2d863922-b (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  263 37316 RETURN     all  --  *      *       203.0.113.125        0.0.0.0/0            MACfa:16:3e:60:78:cd /* Allow traffic from defined IP/MAC pairs. */
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Drop traffic without an IP/MAC allow rule. */

Chain neutron-linuxbri-sg-chain (2 references)
 pkts bytes target     prot opt in     out     source               destination         
 4122  641K neutron-linuxbri-i2d863922-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-out tap2d863922-bc --physdev-is-bridged /* Jump to the VM specific chain. */
  265 37986 neutron-linuxbri-o2d863922-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in tap2d863922-bc --physdev-is-bridged /* Jump to the VM specific chain. */
  515 61879 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain neutron-linuxbri-sg-fallback (2 references)
 pkts bytes target     prot opt in     out     source               destination         
 3872  617K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Default drop rule for unmatched traffic. */
root@compute1:~# 

neutron-XXX都是OpenStack Neutron配置的相关的链。

neutron-linuxbri-XXX 是 OpenStack Neutron 中与 Linux Bridge 插件相关的自定义链,是由 Neutron 在使用 Linux Bridge 网络驱动时自动创建和管理的。

OpenStack管理的虚机的流量都是需要经过FORWARD链。

OpenStack创建的安全组就是通过在filter表的FORWARD链插入相关规则实现。

1/ 虚机入站和出站流量首先送到安全组链(neutron-linuxbri-sg-chain)

-A FORWARD -j neutron-filter-top
-A FORWARD -j neutron-linuxbri-FORWARD

-A neutron-filter-top -j neutron-linuxbri-local

-A neutron-linuxbri-FORWARD -m physdev --physdev-out tap2d863922-bc --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-linuxbri-sg-chain
-A neutron-linuxbri-FORWARD -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-linuxbri-sg-chain

-A neutron-linuxbri-sg-chain -m physdev --physdev-out tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-i2d863922-b

-A neutron-linuxbri-sg-chain -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-o2d863922-b

-A neutron-linuxbri-sg-chain -j ACCEPT

neutron-filter-top 是一个顶层链,通常被插入到 FORWARDOUTPUT 链中。它的主要功能是将流量转发到其他 Neutron 定义的链进行进一步处理。
neutron-linuxbri-local一般表示和本地(local)机器上的网络接口或规则有关,通常用于处理本地出入的流量。

  • 本文中neutron-linuxbri-local有定义,但没有定义规则。"被跳转的链存在但没有任何规则,流量会"返回"到原来的链,继续后面的规则执行。"
    neutron-linuxbri-FORWARD 是一个与 Linux Bridge 插件相关的链,用于处理虚拟机的转发流量。
  1. -A neutron-linuxbri-FORWARD
  • -A:表示将规则添加到一个已经存在的链中。

  • neutron-linuxbri-FORWARD:这是一个已经存在的链,通常用于处理通过 Linux Bridgelinuxbridge 网络插件)转发的流量。


  1. -m physdev
  • -m physdev:这是一个用于匹配物理设备的扩展模块,用来标识和过滤基于 物理设备(比如虚拟机网卡、物理网卡等)的流量。

  1. --physdev-out tap2d863922-bc
  • --physdev-out:表示匹配流量从指定的物理接口出去。

  • tap2d863922-bc:这是虚拟机的网络接口设备名,通常是 虚拟网卡 ,代表这条规则仅适用于通过此虚拟网卡发送的流量。这个 tap 接口可能是由 Open vSwitch (OVS)Linux Bridge(由 Neutron 管理)创建的。

    tap2d863922-bc 可能是 Neutron 创建的某个虚拟机接口的名称,每个虚拟机都有类似的 tap 接口。

    注意:physdev-out是流量从网桥发往虚拟机的方向,即虚拟机入站流量;physdev-in是流量从虚拟机进入网桥的方向,即虚拟机出站流量。


  1. --physdev-is-bridged
  • --physdev-is-bridged:指定这个流量是通过 桥接网络 (即 bridge 模式)发送的。此标志确保该规则仅匹配通过桥接设备转发的流量。

    这个标志通常在 Neutron 使用 Linux Bridge 或 OVS 作为网络插件时出现。


  1. -m comment --comment "Direct traffic from the VM interface to the security group chain."
  • -m comment:这是一个用于添加注释的模块,它可以帮助解释规则的目的。

  • --comment "Direct traffic from the VM interface to the security group chain.":这段注释表明,这条规则的目的是将流量从虚拟机接口直接转发到安全组链(neutron-linuxbri-sg-chain)。


  1. -j neutron-linuxbri-sg-chain
  • -j:表示 跳转到(jump to)指定的链。

  • neutron-linuxbri-sg-chain:表示将匹配到的流量转发到 neutron-linuxbri-sg-chain 链,通常这个链是用来处理与安全组相关的规则。也就是说,所有来自虚拟机接口(如 tap2d863922-bc)的流量将被送往 安全组链 进行检查和处理

neutron-linuxbri-sg-chain对流量进行进一步处理,虚机的入站流量送到该虚机的入站流量安全组链处理(neutron-linuxbri-i2d863922-b),虚机的出站流量送到该虚机的出站流量安全组链处理(neutron-linuxbri-o2d863922-b),最后接受所有未被前面规则匹配的流量。

2/ 虚机的入站流量送到该虚机的入站流量安全组链处理(neutron-linuxbri-i2d863922-b)

-A neutron-linuxbri-sg-chain -m physdev --physdev-out tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-i2d863922-b

  • -A neutron-linuxbri-sg-chain :将这条规则添加到 neutron-linuxbri-sg-chain 链。

  • -m physdev --physdev-out tap2d863922-bc :匹配来自虚拟机接口 tap2d863922-bc 的虚拟机入站流量。

  • --physdev-is-bridged:确保这个流量是通过桥接设备(bridge)发送的,表示该流量经过了桥接网络。

  • --comment "Jump to the VM specific chain." :注释解释该规则的作用是跳转到虚拟机特定的链

  • -j neutron-linuxbri-i2d863922-b :这条规则将流量跳转到 neutron-linuxbri-i2d863922-b 链。这个链的规则与虚拟机的入站流量相关(控制该虚拟机接收流量的安全组规则)。

作用:

  • 如果流量从虚拟机接口 tap2d863922-bc 发往虚拟机(即虚拟机入站流量),它会跳转到 neutron-linuxbri-i2d863922-b 链进行进一步处理。

3/ 虚机的出站流量送到该虚机的出站流量安全组链处理(neutron-linuxbri-o2d863922-b)

-A neutron-linuxbri-sg-chain -m physdev --physdev-in tap2d863922-bc --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-linuxbri-o2d863922-b

-A neutron-linuxbri-sg-chain :将这条规则添加到 neutron-linuxbri-sg-chain 链。

  • -m physdev --physdev-in tap2d863922-bc :匹配流量进入虚拟机接口 tap2d863922-bc 的虚拟机出站流量。

  • --physdev-is-bridged:确保这个流量是通过桥接设备发送的。

  • --comment "Jump to the VM specific chain." :注释表示这条规则的作用是跳转到虚拟机特定的链

  • -j neutron-linuxbri-o2d863922-b :这条规则将流量跳转到 neutron-linuxbri-o2d863922-b 链。这个链的规则与虚拟机的出站流量相关(控制该虚拟机发送流量的安全组规则)。

作用:

  • 如果流量是从虚拟机流入虚拟机接口 tap2d863922-bc(即虚拟机出站流量,虚拟机接口连接虚拟机的网卡),它会跳转到 neutron-linuxbri-o2d863922-b 链进行进一步处理。

七、虚机入站流量安全组链规则解读(neutron-linuxbri-i2d863922-b)

-A neutron-linuxbri-i2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN

-A neutron-linuxbri-i2d863922-b -d 203.0.113.125/32 -p udp -m udp --sport 67 --dport 68 -j RETURN

-A neutron-linuxbri-i2d863922-b -d 255.255.255.255/32 -p udp -m udp --sport 67 --dport 68 -j RETURN

-A neutron-linuxbri-i2d863922-b -m set --match-set NIPv415dfe688-d6fc-4231-a670- src -j RETURN

-A neutron-linuxbri-i2d863922-b -p icmp -j RETURN

-A neutron-linuxbri-i2d863922-b -p tcp -m tcp --dport 22 -j RETURN

-A neutron-linuxbri-i2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP

-A neutron-linuxbri-i2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback

neutron-linuxbri-i2d863922-b定义了针对来自虚拟机接口(tap2d863922-bc)的虚拟机入站流量的处理方式。

  1. 第一条规则:

-A neutron-linuxbri-i2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN

  • -A neutron-linuxbri-i2d863922-b :将这条规则添加到 neutron-linuxbri-i2d863922-b 链。

  • -m state --state RELATED,ESTABLISHED:匹配已经建立的或相关的连接的流量。即这些流量属于一个已经存在的连接或会话。

  • --comment "Direct packets associated with a known session to the RETURN chain." :注释表示该规则的作用是将已知会话的流量直接跳转到 RETURN

  • -j RETURN :流量会跳转到 RETURN 链,通常这意味着会话相关的流量被允许通过或交给上级链进行进一步处理。

  1. 第二条规则:

-A neutron-linuxbri-i2d863922-b -d 203.0.113.125/32 -p udp -m udp --sport 67 --dport 68 -j RETURN

  • -d 203.0.113.125/32 :匹配目的 IP 地址为 203.0.113.125 的流量。

  • -p udp:匹配 UDP 协议的流量。

  • --sport 67 --dport 68:匹配源端口为 67,目标端口为 68 的流量,这通常是 DHCP 流量(DHCP 客户端与服务器之间的通信端口)。

  • -j RETURN :该流量会被直接跳转到 RETURN 链,通常表示允许或不做任何处理。

  1. 第三条规则:

-A neutron-linuxbri-i2d863922-b -d 255.255.255.255/32 -p udp -m udp --sport 67 --dport 68 -j RETURN

  • -d 255.255.255.255/32:匹配目的地址为广播地址(255.255.255.255)的流量。

  • -p udp:匹配 UDP 协议。

  • --sport 67 --dport 68:匹配源端口为 67,目标端口为 68 的流量,同样是 DHCP 流量。

  • -j RETURN :此流量也会跳转到 RETURN 链,通常表示允许广播流量通过。

  1. 第四条规则:

-A neutron-linuxbri-i2d863922-b -m set --match-set NIPv415dfe688-d6fc-4231-a670- src -j RETURN

  • -m set --match-set NIPv415dfe688-d6fc-4231-a670- src :匹配源 IP 地址属于 NIPv415dfe688-d6fc-4231-a670- 这个 IP 地址集合的流量。这个集合可能是事先定义的 IP 地址池或范围。

  • -j RETURN :这些流量会直接跳转到 RETURN 链,可能是允许这些流量通过或跳过其他检查。

  1. 第五条规则:

-A neutron-linuxbri-i2d863922-b -p icmp -j RETURN

  • -p icmp:匹配 ICMP 协议的流量(例如 Ping 请求)。

  • -j RETURN :此类流量会直接跳转到 RETURN 链,通常表示允许 ICMP 流量通过。

  1. 第六条规则:

-A neutron-linuxbri-i2d863922-b -p tcp -m tcp --dport 22 -j RETURN

  • -p tcp:匹配 TCP 协议的流量。

  • --dport 22:匹配目标端口为 22 的流量,通常是 SSH 流量。

  • -j RETURN :允许目标端口为 22 的流量直接通过,跳转到 RETURN 链。

  1. 第七条规则:

-A neutron-linuxbri-i2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP

  • -m state --state INVALID:匹配无效状态的流量,通常这些流量与已知连接不匹配,可能是损坏或伪造的包。

  • --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack.":注释解释这条规则会丢弃看起来像是与现有连接相关的流量(例如,TCP ACK/FIN 包),但没有连接跟踪条目。

  • -j DROP:丢弃这些无效的包。

  1. 第八条规则:

-A neutron-linuxbri-i2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback

  • -j neutron-linuxbri-sg-fallback :如果流量没有匹配到以上规则,它将跳转到 neutron-linuxbri-sg-fallback 链。这个链可能包含其他的处理逻辑,例如安全组检查或丢弃流量。

注1:其中5、6条虚拟机入站规则,是之前添加到default安全组当中的。

注2:第4条规则涉及的IP地址集合,可以通过以下命令查看:

复制代码
root@compute1:~# ipset list
Name: NIPv415dfe688-d6fc-4231-a670-
Type: hash:net
Revision: 7
Header: family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xc7f31013
Size in memory: 504
References: 1
Number of entries: 1
Members:
203.0.113.125

注3:查看连接跟踪(connection tracking)信息,可以使用conntrack命令。这个工具用于查看和管理内核中的连接跟踪表。

复制代码
root@compute1:~# conntrack -L
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59454 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59454 [ASSURED] mark=0 use=1
udp      17 2 src=203.0.113.90 dst=239.255.255.250 sport=49337 dport=1900 [UNREPLIED] src=239.255.255.250 dst=203.0.113.90 sport=1900 dport=49337 mark=0 zone=4097 use=1
tcp      6 112 TIME_WAIT src=10.0.20.12 dst=10.0.20.11 sport=41734 dport=8778 src=10.0.20.11 dst=10.0.20.12 sport=8778 dport=41734 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59474 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59474 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=47200 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=47200 [ASSURED] mark=0 use=1
tcp      6 300 ESTABLISHED src=10.0.20.1 dst=10.0.20.12 sport=9901 dport=22 src=10.0.20.12 dst=10.0.20.1 sport=22 dport=9901 [ASSURED] mark=0 use=1
tcp      6 431992 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59486 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59486 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59470 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59470 [ASSURED] mark=0 use=1
tcp      6 431991 ESTABLISHED src=203.0.113.90 dst=203.0.113.125 sport=2101 dport=22 src=203.0.113.125 dst=203.0.113.90 sport=22 dport=2101 [ASSURED] mark=0 zone=4097 use=1
tcp      6 51 TIME_WAIT src=10.0.20.12 dst=10.0.20.11 sport=47018 dport=8778 src=10.0.20.11 dst=10.0.20.12 sport=8778 dport=47018 [ASSURED] mark=0 use=1
tcp      6 431984 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59440 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59440 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59504 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59504 [ASSURED] mark=0 use=1
tcp      6 431984 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59432 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59432 [ASSURED] mark=0 use=1
udp      17 15 src=203.0.113.90 dst=224.0.0.251 sport=5353 dport=5353 [UNREPLIED] src=224.0.0.251 dst=203.0.113.90 sport=5353 dport=5353 mark=0 zone=4097 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59418 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59418 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=48460 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=48460 [ASSURED] mark=0 use=1
tcp      6 75 TIME_WAIT src=203.0.113.90 dst=203.0.113.125 sport=2078 dport=22 src=203.0.113.125 dst=203.0.113.90 sport=22 dport=2078 [ASSURED] mark=0 zone=4097 use=1
tcp      6 428627 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=55168 dport=3306 src=10.0.20.11 dst=10.0.20.12 sport=3306 dport=55168 [ASSURED] mark=0 use=1
tcp      6 431992 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59494 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59494 [ASSURED] mark=0 use=2
tcp      6 57 CLOSE_WAIT src=10.0.20.12 dst=10.0.20.11 sport=33748 dport=8778 src=10.0.20.11 dst=10.0.20.12 sport=8778 dport=33748 [ASSURED] mark=0 use=1
tcp      6 431987 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=41996 dport=9696 src=10.0.20.11 dst=10.0.20.12 sport=9696 dport=41996 [ASSURED] mark=0 use=1
udp      17 24 src=203.0.113.90 dst=239.255.255.250 sport=62791 dport=1900 [UNREPLIED] src=239.255.255.250 dst=203.0.113.90 sport=1900 dport=62791 mark=0 zone=4097 use=1
tcp      6 431992 ESTABLISHED src=127.0.0.1 dst=127.0.0.1 sport=37286 dport=38013 src=127.0.0.1 dst=127.0.0.1 sport=38013 dport=37286 [ASSURED] mark=0 use=1
tcp      6 431986 ESTABLISHED src=10.0.20.12 dst=10.0.20.11 sport=59512 dport=5672 src=10.0.20.11 dst=10.0.20.12 sport=5672 dport=59512 [ASSURED] mark=0 use=1
conntrack v1.4.6 (conntrack-tools): 24 flow entries have been shown.
root@compute1:~# conntrack -L | grep 203.0.113.125
conntrack v1.4.6 (conntrack-tools): 22 flow entries have been shown.
tcp      6 431960 ESTABLISHED src=203.0.113.90 dst=203.0.113.125 sport=2101 dport=22 src=203.0.113.125 dst=203.0.113.90 sport=22 dport=2101 [ASSURED] mark=0 zone=4097 use=1
tcp      6 44 TIME_WAIT src=203.0.113.90 dst=203.0.113.125 sport=2078 dport=22 src=203.0.113.125 dst=203.0.113.90 sport=22 dport=2078 [ASSURED] mark=0 zone=4097 use=1
root@compute1:~# 

🧑‍💻 入站流量安全组链小结

这些规则在 neutron-linuxbri-i2d863922-b 链中处理虚拟机入站流量。根据不同的流量特征(如协议、端口、状态等),它们会:

  1. 允许已知会话的流量通过(如已经建立的连接)。

  2. 允许 DHCP、ICMP、SSH 等特定流量通过

  3. 丢弃无效的、无法匹配连接的流量(如无效的 TCP 包)。

  4. 将未匹配的流量发送到回退链,以便进一步处理。

八、虚机出站流量安全组链规则解读(neutron-linuxbri-o2d863922-b)

-A neutron-linuxbri-o2d863922-b -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN

-A neutron-linuxbri-o2d863922-b -j neutron-linuxbri-s2d863922-b

-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN

-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 67 --dport 68 -m comment --comment "Prevent DHCP Spoofing by VM." -j DROP

-A neutron-linuxbri-o2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN

-A neutron-linuxbri-o2d863922-b -j RETURN

-A neutron-linuxbri-o2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP

-A neutron-linuxbri-o2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback

其他相关安全组链:

-A neutron-linuxbri-s2d863922-b -s 203.0.113.125/32 -m mac --mac-source fa:16:3e:60:78:cd -m comment --comment "Allow traffic from defined IP/MAC pairs." -j RETURN

-A neutron-linuxbri-s2d863922-b -m comment --comment "Drop traffic without an IP/MAC allow rule." -j DROP

-A neutron-linuxbri-sg-fallback -m comment --comment "Default drop rule for unmatched traffic." -j DROP

neutron-linuxbri-i2d863922-b定义了针对来自虚拟机接口(tap2d863922-bc)的虚拟机出站流量的处理方式。

  1. 第一条规则:

-A neutron-linuxbri-o2d863922-b -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN

  • -s 0.0.0.0/32 -d 255.255.255.255/32 :匹配源地址为 0.0.0.0(通常是 DHCP 客户端的源地址)和目标地址为广播地址 255.255.255.255 的流量。

  • -p udp:匹配 UDP 协议。

  • --sport 68 --dport 67:匹配源端口为 68,目标端口为 67 的流量,这是 DHCP 客户端与 DHCP 服务器之间的标准端口。

  • -j RETURN :允许这类 DHCP 客户端的流量通过,跳转到 RETURN 链。

  1. 第二条规则:

-A neutron-linuxbri-o2d863922-b -j neutron-linuxbri-s2d863922-b

  • -j neutron-linuxbri-s2d863922-b :如果流量没有匹配前面规则,它将跳转到 neutron-linuxbri-s2d863922-b 链,这可能是针对其他流量进行的进一步处理。

  • neutron-linuxbri-s2d863922-b 链,主要用于 基于 IP 地址和 MAC 地址的流量控制, 对于没有与 IP/MAC 地址对匹配的流量,直接丢弃

  1. 第三条规则:

-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN

  • 这条规则和第一条规则相同,允许源端口为 68,目标端口为 67 的 DHCP 客户端流量。
  1. 第四条规则:

-A neutron-linuxbri-o2d863922-b -p udp -m udp --sport 67 --dport 68 -m comment --comment "Prevent DHCP Spoofing by VM." -j DROP

  • -p udp:匹配 UDP 协议。

  • --sport 67 --dport 68:匹配源端口为 67,目标端口为 68 的流量,这是 DHCP 服务器与客户端的标准端口。

  • -j DROP丢弃任何源端口为 67,目标端口为 68 的流量,防止虚拟机进行 DHCP 欺骗(即伪造 DHCP 服务器响应)。

  1. 第五条规则:

-A neutron-linuxbri-o2d863922-b -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN

  • -m state --state RELATED,ESTABLISHED:匹配与已知会话相关的流量(即已建立或相关的连接)。

  • -j RETURN :流量会直接跳转到 RETURN 链,表示这些流量可以继续通过(通常是已建立的连接或会话)。

  1. 第六条规则:

-A neutron-linuxbri-o2d863922-b -j RETURN

  • -j RETURN :没有条件的 RETURN,这意味着流量直接返回,通常是默认的接受行为。

  • 由于这条规则没有指定任何过滤条件(如 -s、-d、-p 等),它会匹配所有流量。因此,只要流量经过了 neutron-linuxbri-o2d863922-b 链,它就会立即匹配到这一条规则,并且流量会跳转到 RETURN 链。这会使得其他规则(比如第 7 条和第 8 条规则)几乎没有机会被执行。。

  1. 第七条规则:

-A neutron-linuxbri-o2d863922-b -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP

  • -m state --state INVALID:匹配无效状态的流量,通常是一些无法匹配已建立连接的包,例如非法的 TCP ACK/FIN 包。

  • -j DROP丢弃这些无效的流量包。

  1. 第八条规则:

-A neutron-linuxbri-o2d863922-b -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-linuxbri-sg-fallback

  • -j neutron-linuxbri-sg-fallback :如果流量没有匹配前面所有的规则,它将跳转到 neutron-linuxbri-sg-fallback 链,进行进一步的安全组处理。

🧑‍💻 出站流量安全组链小

这些规则主要负责处理 虚拟机到外部网络的出站流量,特别关注 DHCP 流量和安全性。它们的作用包括:

  1. 允许 DHCP 客户端的流量通过(源端口 68,目标端口 67)。

  2. 防止虚拟机进行 DHCP 欺骗(丢弃源端口 67,目标端口 68 的流量)。

  3. 允许已知会话的流量通过 ,跳转到 RETURN 链。

  4. 丢弃无效的、无法匹配已知连接的流量(如无效的 TCP 包)。

  5. 未匹配的流量被送到回退链(fallback),进行额外的安全组处理。

九、总结

OpenStack安全组是在计算节点本机上,通过iptables实现,不是在虚机(实例)中实现。

相关推荐
伤不起bb11 分钟前
MySQL 高可用
linux·运维·数据库·mysql·安全·高可用
tmacfrank3 小时前
网络编程中的直接内存与零拷贝
java·linux·网络
向上的车轮5 小时前
MATLAB学习笔记(七):MATLAB建模城市的雨季防洪排污的问题
笔记·学习·matlab
躺着听Jay5 小时前
Oracle-相关笔记
数据库·笔记·oracle
田梓燊5 小时前
数学复习笔记 19
笔记·线性代数·机器学习
QQ2740287565 小时前
Soundness Gitpod 部署教程
linux·运维·服务器·前端·chrome·web3
qwfys2006 小时前
How to configure Linux mint desktop
linux·desktop·configure·mint
南方以南_6 小时前
Ubuntu操作合集
linux·运维·ubuntu
逼子格6 小时前
硬件工程师笔记——二极管Multisim电路仿真实验汇总
笔记·嵌入式硬件·硬件工程师·multisim·硬件工程师学习·电子器件·电路图
龙湾开发7 小时前
计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 10.增强表面细节(二)法线贴图
c++·笔记·学习·图形渲染·贴图