Linux难以处理的IPSec



开发IT基础架构迟早要与大型组织的任何服务集成。 例如,这可以是银行或电信运营商。 通常,大型组织具有完善的信息安全策略,特别是要求通过加密渠道IPSec在其外部基础结构上实现服务。 同时,在小型启动组织中,没有组织这种方案的经验,并且从设备来看,只有Linux带有VDS。 而且,令我惊讶的是,Runet中几乎没有描述Linux故障排除工具的材料。 让我们尝试消除这种差距,并描述设置的实际部分。

该服务的一般方案如下所示。 通常,在大型组织中,一切都已经标准化,已投入使用,各种可能的加密和其他网络段都在单独的设备(tsiska瞻博网络和类似的设备)上完成,更重要的是,由个人 (也许下图中的每个蓝色框表示)由不同的人服务)。 您有一台将用来启动服务并组织IPSec的虚拟机。



请注意,IPSec本身在一个IP地址之间进行组织(在我的示例中为10.0.255.1 <-> 10.0.1.1 ),服务本身在其他IP地址之间进行组织( 192.168.255.1<-> 192.168.1.1 )。 这种方案也称为IPSec网络-网络

一个简单的例子是,您在一家年轻但雄心勃勃的SuperService公司工作,并且需要与MegaTelecom的封闭API进行交互 。 您的基础架构是一台VDS服务器,您的合作伙伴基础架构是一堆网络和服务器设备。 该任务分为两个阶段:

  1. 组织运输(如何进行互通)。
  2. 配置服务(直接在服务器上运行应用程序)。

因此, SuperService经理决定组织与某个大型组织的连接以解决业务问题。 他求助于MegaTelecom ,他们向他发送了连接的技术规格 。 这些条件之一就是IPSec 。 这种情况以excel板的形式出现,我在下面介绍了一个示例。 在图片中,我用黄色突出显示了技术上重要的参数。 格式可能有所不同,但本质保持不变。



最初,它不属于您本人,必须填写并发送给合作伙伴以供批准。 达成协议后,您可以坐下来尝试调整Linux机器。

IPSec概念


接下来,我将为根本不熟悉技术的人提供一些理论。 我将进一步描述的都是纯以太网和IPv4。 我将不涉及加密和密钥交换算法,而是将重点放在网络部分。

IPSec-用于组织安全连接的一组技术和协议。

与其他隧道技术(GRE,PPP,L2TP甚至MPLS-TE)不同,没有为IPSec创建显式隧道接口,可以通过该接口路由流量。 取而代之的是,IPSec提供了所谓的安全关联(SA)的概念。 SA是从一个网络设备到另一网络设备的隧道。 但是,请不要忘记,按照通常的说法, SA不是网络接口,经典路由在这里不起作用。 在这里, 安全策略(SP)概念代替了路由表。 我们明确规定了访问列表(ACL)之类的内容,以通过特定的SA传递流量。 所有这些东西都在所谓的ISAKMP框架中定义。
ISAKMP -IPSec程序的描述,在文献中他们将其称为框架。 它描述了术语SA,SP,SAD(安全关联数据库),SPD(安全策略数据库),安装辅助隧道的必要性……ISAKMP的设计目的是不依赖于隧道技术,身份验证算法和加密。 他只是简单介绍了必要的定义。

IKE(v1 / 2) -直接身份验证协议。 他已经实现了密钥交换算法及其应用。

由于思科的概念,ISAKMP和IKE现在被视为同义词。
在加密流量之前,各方必须就此加密的参数(和密钥)达成一致。 为此,一条辅助隧道一直在两侧之间架起(也称为ISAKMP隧道),该隧道一直在运行。 此双向隧道是UDP连接(默认情况下在端口500上)。 要组织此辅助隧道,各方必须相互认证(密码必须匹配)。 这是通过IKEv1 / 2(Internet密钥交换)协议完成的。 双方已经在ISAKMP组织的隧道上同意直接加密用户流量。

IPSec组织本身分为两个阶段:

  1. 创建ISAKMP辅助隧道
  2. 创建用户数据隧道

如我所写,在IPSec概念中(或者在ISAKMP概念中),隧道称为SA

第一阶段(ISAKMP SA组织)可以以两种方式执行:

  1. 主要 -各方交替交换协商参数。 它被认为更安全,用于永久性渠道(我们的情况)。
  2. 积极的 -在一条消息中,启动器发送所有必要的协调参数;在连接远程用户进行临时会话时使用(以使其更快)。

您必须了解, 主要的 SA隧道是单向的 。 对于通过IPSec通道的双向数据传输,必须有两个隧道:源(src)→接收器(dst),反之亦然。

在所有加密方法中,都会将其他标头添加到原始IP数据包中,从而进行封装。 此封装有两种方法-AH(认证标头)ESP(封装安全有效载荷) 。 AH仅认证数据包(由发送方进行数字签名),ESP并认证(签名)和加密。 如今,AH几乎从未使用过,所有内容都打包在ESP中。

您可以加密和认证源IP数据包,而无需考虑IP标头(传输模式)或与其一起使用(隧道模式)。 当计划使用其他技术(而不是IPSec / ESP)来组织其隧道时, 使用传输 。 例如,GRE,l2tp,ppp。 为了将某些服务连接到大型组织的内部基础结构,实际上不使用它。 我使用此方案通过IPSec将多个办公室合并为一个VPN。 我们对隧道模式更感兴趣。 从图片中可以看到,此处添加了一个附加的IP标头。


顺便说一句,有一个使用AH封装的真实示例。 假设我们有两个连接到不同路由器的网络。 主机应使用1500字节的MTU传输信息,而不会产生碎片,但是我们有一个仅支持1380字节的中间部分。 整个轨道是受信任的。 我们可以利用IPSec不会创建隧道接口这一事实,在传统意义上,IPSec不会通过该接口路由流量。 我们将创建AH类型的隧道SA (无需加密),然后流量将流向该隧道。 仅外部IP数据包(根据外部IP报头)将在流量中分段,内部的IP数据包将重新组装而不会发生变化。



请注意, ESP在TCP / UDP传输之前上升。 还记得IP字段有一个Protocol字段吗? 基于此字段,网络设备(和终端主机)正确处理IP数据包。 因此,对于ESP,其数量为50。可以在Wiki上查看此字段的协议的完整列表,这可能非常有用。

缺少传输层头(TCP / UDP / ICMP已经加密!)对NAT等技术施加了限制。 请记住,具有端口转换功能的NAT(过载,PAT,MASQARADE,它具有许多名称)在传输协议端口的基础上工作。 而且在加密的IPSec隧道中,它们不是! 为了克服此问题,存在诸如IPSec NAT-Traversal(NAT-T)的技术 。 在第一阶段中,双方同意使用NAT-T。 如果双方都支持NAT-T(甚至在相同的UDP端口上),则UDP报头将添加到生成的隧道中以进行通信,通过该隧道,数据包已经通过具有网络地址转换的路由器。

隧道本身不会上升,您需要将流量引导到那里。 正如我在上面所写,路由规则在这里不起作用,您需要编写安全策略(SP)

策略由源地址,目的地址,方向(输入,输出,转发)和用户隧道参数组成(此处将仅描述ESP是AH,隧道版本还是传输)。 这更像是为NAT组织规则。 NAT也没有足够的路由表条目。 在这里,规则也指示在哪里,在哪里和如何 ,而不是在哪里和通过什么 。 而且,如果手部移动不正确,则可能会阻止远程服务器上的所有通信。
所有IPSec操作都添加开销标头。 至少他们会从原始数据包中又吃掉40个字节。 因此,例如,对于用于PPPoE的1380字节连接的标准MTU,实际MTU将小于1340。

Linux上的IPSec


让我们使用DEB分布示例进行练习。 我将仅考虑具有基于预共享密钥(PSK)的授权的情况,我们将从本文开头配置该方案。

内核本身支持IPSec本身,但是这种支持非常有限。 实际上,功能强大的模块仅涉及加密和已接收(已传输到内核)的密钥(数据包处理)。 为了将需要处理流量的参数和规则传递到那里,您需要单独的软件。 作为此类软件,有几种解决方案:

  1. KAME从BSD迁移
  2. xSWAN(strongswan,freeswan,libreswan等)
  3. 岸墙

在我看来,这是最简单(最可预测)的KAME版本,我们将继续扭转它。

 # deb-       root@localhost: ~# apt-get install racoon ipsec-tools 

传统上,KAME由两个部分组成

  1. 浣熊守护程序,用于控制ISAKMP隧道。
  2. Setkey实用程序,用于管理带有数据的SA隧道。

让我们从第一个开始。 Racoon负责IKE下的隧道授权设置。 这是一个守护程序,它配置有一个配置文件( /etc/racoon.conf ),由常规的初始化脚本( /etc/init.d/racoon <start|stop|restart>/etc/init.d/racoon <start|stop|restart>

根@本地主机:〜#猫/etc/racoon.conf
 #      remote  sainfo     # #      PSK  path pre_shared_key "/etc/racoon/psk.txt"; log debug; listen { #  ,      ISAKMP  isakmp 10.0.1.1 [500]; strict_address; } #   remote      IPSec. #      tunnel-group  ASA. #   IP-   anonymous #          . #     user-network # remote anonymous remote 10.0.255.1 { nat_traversal off; exchange_mode main; my_identifier address 10.0.1.1; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method pre_shared_key; dh_group modp1024; lifetime time 86400 sec; } } #   IPSec.  transform-set  ASA. # # ,      #       . #         # sainfo address <src> address <dst> #      ,       # sainfo anonymous sainfo address 192.168.1.1 any address 192.168.255.1 any { pfs_group modp1024; lifetime time 28800 sec; encryption_algorithm 3des; authentication_algorithm hmac_sha1; compression_algorithm deflate; } 


根@本地主机:〜#猫/etc/racoon/psk.txt
 #   PSK- #  <REMOTE IP ADDR> <PASSWORD> #  -      ,     racoon 10.0.255.1 SUPERPASSWORD 


和往常一样, man 5 racoon.conf细节

接下来,我们将使用setkey实用程序。 它还以守护程序( /etc/init.d/setkey <start|stop|restart>/etc/init.d/setkey <start|stop|restart> ,但实际上它运行脚本/etc/ipsec-tools.conf 。 就像我说的,它已经为用户流量设置了创建隧道。 即为它们设置SA和SP 。 这有点像ASA上的加密映射 。 对我们而言,最简单的选择是仅添加SP。 然后,将根据浣熊设置中指定的第二阶段的参数自动构建SA。

但是可能根本不使用浣熊的第二阶段参数,而是通过此实用程序设置SA。 详细信息和语法可以在man 8 setkey找到。 但我将举一个最简单的配置示例。

根@本地主机:〜#cat /etc/ipsec-tools.conf
 flush; spdflush; spdadd 192.168.1.1/32 192.168.255.1/32 any -P out ipsec esp/tunnel/10.0.1.1-10.0.255.1/require; spdadd 192.168.255.1/32 192.168.1.1/32 any -P in ipsec esp/tunnel/10.0.255.1-10.0.1.1/require; 


当前, setroute实用程序由iproute2模块复制。
其中有两个记录管理团队SA和SP。

  1. ip xfrm 状态
  2. ip xfrm 政策

除了管理此实用程序外,您还可以查看应用于流量的已组织SA和SP的状态。 在man 8 ip-xfrm更多详细信息。
再看看原始平板电脑。 IPSec和服务有不同的IP地址。 内部IP地址正在Megatelecom基础结构内部进行过滤。 但是我们只有一个虚拟机。 内部IP地址应以某种方式出现在其上,并且进入隧道的数据包应从该地址发出。 有几种方法可以实现此方案:

  1. 一条静态路由,没有检测到停止,但带有外向接口和IP地址的明确指示。
  2. 根据基于策略的路由(Linux上的PBR aka ip rule )定义路由。
  3. 地址转换( NAT / MASQARADE )。

以我的观点,第一种选择在这里是合适的。

我们可以在接口中添加其他(辅助)IP地址,但最好为此接口创建别名
root@localhost: ~# ip addr add 192.168.1.1/32 dev eth1 label eth1:1
并配置从该IP地址到Megatelecom服务器的路由。
root@localhost: ~# ip route add 192.168.255.1/32 dev eth1:1 src 192.168.1.1
但是,如果您这样做,将什么也不会开始。 事实是,当以这种形式添加路由时,Linux工作站将尝试确定收件人的MAC地址,它将通过ARP进行操作。计算机将发送Who has IP 192.168.255.1 ARP请求。 由于192.168.255.1与192.168.1.1(掩码/ 32!)不在同一网络上,因此不会对ARP做出任何响应。 但是,当您尝试连接时,本地IP地址不会返回No route to host 。 为了解决这个问题,我们需要设置一个静态ARP记录:
root@localhost: ~# arp -s 192.168.255.1 00:00:00:00:00:01 -i eth1:1
这样的生活hack。 顺便说一句,这种操作可能不会导致Linux IP堆栈的正确操作。 在一种情况下, ip route命令无法产生预期的结果,因此有必要重新启动网络堆栈。

健康检查



别忘了,隧道只有在有车流进来时才会上升! 必须从目的地之前的特定接口(IP地址)开始ping。
root@localhost: ~# ping -I 192.168.1.1 192.168.255.1
稍有延迟,应该从反面答复(除非ICMP在站点上的任何地方都关闭)。

我们可以看到ISAKMP隧道是否已上升。

racoonctl show-sa isakmp
 root@localhost: ~# racoonctl show-sa isakmp Destination Cookies Created 10.0.1.1.500 356a7e11111a93f:367111530375c065 2018-10-02 09:18:28 


我们还可以看到带有用户数据的隧道。

racoonctl show-sa esp
 10.0.1.1 10.0.255.1 esp mode=tunnel spi=2148175815(0x800a8fc7) reqid=0(0x00000000) E: 3des-cbc 799e587f 6a2b4b78 5590cc2a 3d3ee331 f7e7f472 01abcdef A: hmac-sha1 01c5161f 46679a36 5d07ee9d f159fc9a 01abcdef seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Oct 2 09:22:44 2018 current: Oct 2 10:39:21 2018 diff: 4597(s) hard: 28800(s) soft: 23040(s) last: Oct 2 09:22:45 2018 hard: 0(s) soft: 0(s) current: 84(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 1 hard: 0 soft: 0 sadb_seq=1 pid=3764 refcnt=0 10.0.255.1 10.0.1.1 esp mode=tunnel spi=45614328(0x02b804f8) reqid=0(0x00000000) E: 3des-cbc 97cedcf1 644e8bbb c22b4e2c fa08a874 01abcdef 211ad19e A: hmac-sha1 1ab3e79d 3fd924a0 01abcdef 6c9ac89a 01abcdef seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Oct 2 09:22:44 2018 current: Oct 2 10:39:21 2018 diff: 4597(s) hard: 28800(s) soft: 23040(s) last: Oct 2 09:22:45 2018 hard: 0(s) soft: 0(s) current: 84(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 1 hard: 0 soft: 0 sadb_seq=0 pid=3764 refcnt=0 


tcpdump中查看连接设置逻辑可能很有用。 在这里,您还可以查看连接建立和已加密传输到ESP的流量的阶段。 当然,有破解它的技术,但是通常这个结论已经足够了。

根@本地主机:〜#tcpdump -i eth1主机10.0.255.1
 18:01:06.409631 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 1 I ident 18:01:06.439276 IP 10.0.255.1.500 > 10.0.1.1.500: isakmp: phase 1 R ident 18:01:06.440840 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 1 I ident 18:01:06.475244 IP 10.0.255.1.1.500 > 10.0.1.1.500: isakmp: phase 1 R ident 18:01:06.477032 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 1 I ident[E] 18:01:06.487785 IP 10.0.255.1.500 > 10.0.1.1.500: isakmp: phase 1 R ident[E] 18:01:06.488048 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 2/others I inf[E] 18:01:07.412451 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 2/others I oakley-quick[E] 18:01:07.465363 IP 10.0.255.1.500 > 10.0.1.1.500: isakmp: phase 2/others R oakley-quick[E] 18:01:07.465940 IP 10.0.1.1.500 > 10.0.255.1.500: isakmp: phase 2/others I oakley-quick[E] 18:01:08.467373 IP 10.0.1.1 > 10.0.255.1: ESP(spi=0x7aabfa82,seq=0x1), length 116 18:01:08.480141 IP 10.0.255.1 > 10.0.1.1: ESP(spi=0x0386f867,seq=0x1), length 116 


通过SSH远程连接时,为了不产生一堆窗口,在后台运行tcpdump很方便:

root@localhost: ~# tcpdump -i eth1 -w ipsec.pcap esp &


我们开始ping,telnet,netcat ...

root@localhost: ~# killall tcpdump
root@localhost: ~# tcpdump -vr ipsec.pcap

同样在日志中,您可以看到连接的成功状态。 它显示了IPSec的两个阶段的成功建立。

根@本地主机:〜#cat /var/log/daemon.log
 Oct 3 17:53:26 vm22433 racoon: INFO: IPsec-SA request for 10.0.255.1 queued due to no phase1 found. Oct 3 17:53:26 vm22433 racoon: INFO: initiate new phase 1 negotiation: 10.0.1.1[500]<=>10.0.255.1[500] Oct 3 17:53:26 vm22433 racoon: INFO: begin Identity Protection mode. Oct 3 17:53:26 vm22433 racoon: INFO: received Vendor ID: CISCO-UNITY Oct 3 17:53:26 vm22433 racoon: INFO: received Vendor ID: DPD Oct 3 17:53:26 vm22433 racoon: INFO: received Vendor ID: draft-ietf-ipsra-isakmp-xauth-06.txt Oct 3 17:53:26 vm22433 racoon: INFO: ISAKMP-SA established 10.0.1.1[500]-10.0.255.1[500] spi:ebddc300af62ae42:abcdef0123 Oct 3 17:53:27 vm22433 racoon: INFO: initiate new phase 2 negotiation: 10.0.1.1[500]<=>10.0.255.1[500] Oct 3 17:53:27 vm22433 racoon: INFO: received RESPONDER-LIFETIME: 4608000 kbytes Oct 3 17:53:27 vm22433 racoon: WARNING: attribute has been modified. Oct 3 17:53:27 vm22433 racoon: INFO: IPsec-SA established: ESP/Tunnel 10.0.1.1[500]->10.0.255.1[500] spi=238677(0xe39eabc) Oct 3 17:53:27 vm22433 racoon: INFO: IPsec-SA established: ESP/Tunnel 10.0.1.1[500]->10.0.255.1500] spi=7204011111(0x44b4aaa) 

仅此而已。 剩下的就是将所有必要的操作添加到启动中,然后就可以开始集成应用程序了。

PS:请求通过个人消息报告文章中的所有错误或不准确之处。 当我调整文章时,评论看起来很愚蠢。

Source: https://habr.com/ru/post/zh-CN425079/


All Articles