在此页面上
基于主机的防火墙
本主题讨论 Contrail 网络 2003 版中引入的基于主机的防火墙功能。
基于主机的防火墙概述
Contrail 网络 2003 版为基于主机的防火墙功能提供了 测试版 支持,该功能允许使用 cSRX 设备创建新一代防火墙。新一代防火墙提供了基于应用程序过滤数据包的能力。它们在应用级别提供深度包检测以及入侵检测和防御功能。
过去,vRouter 一直支持创建常规第 4 层防火墙策略。为了创建第 7 层应用级防火墙策略,Contrail 网络使用服务链。但是,服务链仅适用于虚拟网络间流量的情况,不适用于虚拟网络内流量。基于主机的防火墙功能为在同一虚拟网络以及不同网络中始发和结束的流量提供新一代防火墙功能。它使用线路模式下的颠簸,其中防火墙实例不会更改数据包格式或第 2 层标头,而是对数据包应用第 7 层策略。
此外,基于主机的防火墙功能使用基于标记的策略来引导流量。标记是应用防火墙意图的一种简单直观的方法,能够跨越多个 VN,更好地扩展,并且可以在 VMI 级别附加,而不是服务链。您可以使用基于标记的策略将流量引导至基于主机的防火墙实例。策略仅用于引导特定流量,因为基于主机的防火墙实例需要相当数量的计算资源。
此外,基于主机的防火墙提供更接近工作负载的新一代防火墙功能,并可与第三方防火墙功能集成。
部署基于主机的防火墙
执行以下步骤以部署基于主机的防火墙。在此示例中,我们使用 Kubernetes 作为编排平台,因为 Kubernetes 提供了在选定计算节点上实例化基于主机的防火墙实例的灵活性。步骤的高级列表如下所示:
先决条件
使用 contrail-ansible 部署程序或 Contrail 命令安装 Contrail-Kubernetes 安装程序。请参阅 配置 Kubernetes 群集或使用 Contrail 命令 UI 安装独立的 Kubernetes Contrail 群集。
拓扑
请考虑以下示例 Contrail-Kubernetes 拓扑和 instances.yml 文件。

示例 instances.yaml 文件
deployment: orchestrator: kubernetes deployer: contrail-ansible-deployer provider_config: bms: ssh_pwd: <password> ssh_user: username ntpserver: <IP NTP server> domainsuffix: <domain-suffix> instances: server1: provider: bms ip: 10.xx.xx.52 roles: config_database: config: control: analytics_database: analytics: webui: k8s_master: kubemanager: server2: provider: bms ip: 10.xx.xx.53 roles: k8s_node: vrouter: VROUTER_GATEWAY: 77.xx.x.100 global_configuration: CONTAINER_REGISTRY: 50.xx.xx.50:5000 REGISTRY_PRIVATE_INSECURE: True contrail_configuration: CONTRAIL_VERSION: <contrail-version> CLOUD_ORCHESTRATOR: kubernetes CONTROLLER_NODES: 10.xx.xx.52 CONTROL_NODES: 77.xx.xx.20 KUBERNETES_API_NODES: 77.xx.xx.20 KUBERNETES_API_SERVER: 77.xx.xx.20 CONTAINER_REGISTRY: 50.xx.xx.50:5000 REGISTRY_PRIVATE_INSECURE: True VROUTER_GATEWAY: 77.xx.x.100
部署说明
程序
分步过程
部署基于主机的防火墙。
在 Kubernetes 中创建命名空间。命名空间在 Contrail 中创建等效项目。
分步过程
创建命名空间。
kubectl create namespace hbf
在命名空间上启用隔离。
kubectl annotate namespace hbf "opencontrail.org/isolation"="true"
验证命名空间的创建。
kubectl get ns hbf NAME STATUS AGE hbf Active 2d5h
为基于主机的防火墙功能标记计算节点。
分步过程
获取计算节点列表。
kubectl get nodes NAME STATUS ROLES AGE VERSION Server2 Ready <none> 16d v1.12.9 server1 NotReady master 16d v1.12.9
选择基于主机的防火墙功能的节点并对其进行标记。
kubectl label node server type=hbf
其中 server 是 Kubernetes 节点名称, hbf 是标签。
在之前创建的命名空间中创建 Kubernetes 机密对象以拉取 cSRX 映像。
kubectl create secret docker-registry hbf --docker-server=hub.juniper.net/security --docker-username=testuser --docker-password=testpassword -n hbf
hbs在以前创建的命名空间中创建对象。
分步过程
创建包含以下内容的 python 文件,并在 config_api Docker 容器上使用以下命令。
docker exec -it config_api_1 bash (config-api)[root@server /]$ python hbs.py
-
cat hbs.py ---------------- from vnc_api import * from vnc_api.vnc_api import VncApi from vnc_api.vnc_api import Project from vnc_api.vnc_api import HostBasedService from vnc_api.exceptions import NoIdError from vnc_api.gen.resource_xsd import QuotaType hbs_name = ‘hbs’ # any other user defined name can be given project_name = ‘k8s-hbf’ # k8s is the default cluster name # user can change according to their admin_user = 'admin' admin_password = '<admin-password>' admin_project = 'admin' api_node_ip = '10.xx.xx.52' # change according to your topology api_node_port = '8082' # config api port default_domain = 'default-domain' if __name__ == "__main__": api = VncApi( username=admin_user, password=admin_password, tenant_name=admin_project, api_server_host=api_node_ip, api_server_port=api_node_port) '''Creates a project using vnc apis if it doesn’t exist already and enable hbf, if it’s not enabled already''' try: project = api.project_read(fq_name=[default_domain, project_name]) except NoIdError: project = Project(name=project_name) puuid = api.project_create(project) project = api.project_read(fq_name=[default_domain, project_name]) project.set_quota(QuotaType(host_based_service=1)) api.project_update(project) try: hbs = api.host_based_service_read(fq_name=project.fq_name + [hbs_name]) hbs_created = False except NoIdError: hbs = HostBasedService(hbs_name, parent_obj=project) hbs_created = True if hbs_created: api.host_based_service_create(hbs) else: api.host_based_service_update(hbs)
为基于主机的防火墙实例创建守护程序集。默认情况下,基于主机的防火墙实例在所有计算节点上运行。您可以选择在特定计算节点上运行基于主机的防火墙实例,只需标记它们,如 2.b 所示。基于主机的防火墙实例有三个接口。流量流入左侧接口,防火墙功能对数据包执行,流量流出右侧接口。管理接口是默认的容器网络。
分步过程
生成 ds.yaml 文件(如以下示例所示),以使用 cSRX 容器映像创建守护程序集。系统会自动创建左右接口,并使用 hbs “左”和“右”链接到对象,以便通过 cSRX 设备引导为基于主机的防火墙标记的流量。请注意,Kubernetes 对象的名称和值可以根据您的要求进行更改。
cat ds.yaml ----------- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: annotations: opencontrail.org/network: '{"domain":"default-domain", "project":"k8s-hbf", "name":"__hbs-hbf-left__"}' name: left namespace: hbf spec: config: '{"cniVersion":"0.3.0", "type": "contrail-k8s-cni" }' --- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: annotations: opencontrail.org/network: '{"domain":"default-domain", "project":"k8s-hbf", "name":"__hbs-hbf-right__"}' name: right namespace: hbf spec: config: '{"cniVersion":"0.3.0", "type": "contrail-k8s-cni" }' --- apiVersion: apps/v1 kind: DaemonSet metadata: labels: type: hbf name: hbf namespace: hbf spec: selector: matchLabels: type: hbf template: metadata: annotations: k8s.v1.cni.cncf.io/networks: '[{"name":"left"}, {"name":"right"}]' labels: type: hbf spec: containers: - env: - name: CSRX_FORWARD_MODE value: wire image: hub.juniper.net/security/csrx:19.2R1.8 name: csrx securityContext: privileged: true stdin: true tty: false imagePullSecrets: - name: hbf nodeSelector: type: hbf restartPolicy: Always
创建 Kubernetes 对象,进而创建一个 cSRX Pod,在每个命名空间的每个计算节点上具有左右接口。
kubectl create -f ds.yaml
验证对象、守护程序集、网络连接定义和 cSRX 容器。
kubectl get ds -n hbf NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE hbf 1 1 1 1 1 type=hbf 34h kubectl get network-attachment-definitions -n hbf NAME AGE left 34h right 34h [root@nodeg12 ~]# kubectl get pods -n hbf NAME READY STATUS RESTARTS AGE csrx-75ncs 1/1 Running 0 34h csrx-9qxl7 1/1 Running 0 34h
使用以下配置在每个计算节点上配置守护程序集的 cSRX Pod。
set interfaces ge-0/0/0 unit 0 set interfaces ge-0/0/1 unit 0 set security policies default-policy permit-all set security zones security-zone trust interfaces ge-0/0/0.0 set security zones security-zone untrust interfaces ge-0/0/1.0 commit
使用 vnc API 或通过 Contrail 命令在左右接口之间创建网络策略。
只有虚拟网络间流量需要网络策略,虚拟网络内流量不需要网络策略。
docker exec -it config_api_1 bash (config-api)[root@server /]$ python nwp.py cat nwp.py ========== from vnc_api import * from vnc_api import vnc_api from vnc_api.vnc_api import VncApi from vnc_api.vnc_api import Project from vnc_api.exceptions import NoIdError policy_name = 'allow-left-right'. # any policy name if __name__ == "__main__": vn_left = api.virtual_network_read(fq_name= \ [default_domain, project_name, 'k8s-left-pod-network']) vn_right = api.virtual_network_read(fq_name= \ [default_domain, project_name, 'k8s-right-pod-network']) policy_obj = vnc_api.NetworkPolicy(policy_name, network_policy_entries= \ vnc_api.PolicyEntriesType([vnc_api.PolicyRuleType(direction='<>', \ action_list=vnc_api.ActionListType(simple_action='pass'), \ protocol='any', \ src_addresses=[vnc_api.AddressType( virtual_network=vn_left.get_fq_name_str())], \ src_ports=[vnc_api.PortType(-1, -1)], \ dst_addresses=[vnc_api.AddressType( virtual_network=vn_right.get_fq_name_str())], \ dst_ports=[vnc_api.PortType(-1, -1)])]), \ parent_obj=project) api.network_policy_create(policy_obj) vn_left.add_network_policy(policy_obj, \ vnc_api.VirtualNetworkPolicyType(sequence=vnc_api.SequenceType(0, 0))) vn_right.add_network_policy(policy_obj, \ vnc_api.VirtualNetworkPolicyType(sequence=vnc_api.SequenceType(0, 0))) api.virtual_network_update(vn_left) api.virtual_network_update(vn_right)
创建防火墙策略并为防火墙规则启用基于主机的防火墙。
创建标记、应用程序策略集 (APS),以及在项目范围的规则下创建防火墙策略和防火墙规则。在防火墙规则上启用基于主机的防火墙,并将 host_based_service = True。
cat add_hbs_fr.py ------------------ from vnc_api import * from vnc_api import vnc_api from vnc_api.vnc_api import VncApi from vnc_api.vnc_api import Project from vnc_api.vnc_api import HostBasedService from vnc_api.vnc_api import FirewallRule, FirewallServiceType, PortType, FirewallRuleEndpointType from vnc_api.exceptions import NoIdError from vnc_api.vnc_api import ActionListType if __name__ == "__main__": try : rule = api.firewall_rule_read(fq_name=fr_fq_name) #fr_fq_name = [default_domain,project_name,<firewall rule> except NoIdError: rule = api.firewall_rule_create(rule_obj) rule = api.firewall_rule_read(rule_obj) rule.set_action_list( ActionListType(host_based_service=True,simple_action="pass")) api.firewall_rule_update(rule) fwp.add_firewall_rule(rule)
当流量通过基于主机的防火墙时,相应计算节点上的 cSRX 将创建基于主机的防火墙流和相应的会话。
vrouter-agent)[root@nodec61 /]$ flow -l --match 1.xx.xx.251 Flow table(size 161218560, entries 629760) Listing flows matching ([1.xx.xx.251]:*) Index Source:Port/Destination:Port Proto(V) ------------------------------------------------------------------------------------------------------------------- 320632<=>327760 1.xx.xx.251:407 1 (8->12) 2.xx.xx.251:0 (Gen: 4, K(nh):95, Action:F, Flags:, QOS:-1, S(nh):95, Stats:21/2058,SPort 49640, TTL 0, HbsLeft, Sinfo 12.0.0.0) 327760<=>320632 2.xx.xx.251:407 1 (8->12) 1.xx.xx.251:0 (Gen: 3, K(nh):95, Action:F, Flags:, QOS:-1, S(nh):24, Stats:20/1680, SPort 61330, TTL 0, HbsRight, Sinfo 77.xx.xx.21) On csrx ======== root@csrx-7vhn6> show security flow session Session ID: 76342, Policy name: default-policy-logical-system-00/2, Timeout: 4, Valid In: 2.xx.xx.251/407 --> 1.xx.xx.251/128;icmp, Conn Tag: 0x0, If: ge-0/0/1.0, Pkts: 1, Bytes: 98, Out: 1.xx.xx.251/128 --> 2.xx.xx.251/407;icmp, Conn Tag: 0x0, If: ge-0/0/0.0, Pkts: 0, Bytes: 0, Total sessions: 1