|
| 1 | +%description: |
| 2 | +IPsec over IPv6 -- end-to-end drop/deliver assertions (stronger than the ipv6.ini |
| 3 | +fingerprint example, which only pins byte output). Four UDP streams run between two |
| 4 | +IPv6 hosts, each matched by a different Security Policy, proving that all four IPsec |
| 5 | +egress/ingress outcomes behave correctly over IPv6: |
| 6 | + |
| 7 | + app[0] 1000->2000 ESP-protected -> delivered (egress ESP PROTECT, ingress ACCEPT ESP) |
| 8 | + app[1] 1001->2001 BYPASS rule -> delivered (no protection) |
| 9 | + app[2] 1002->2002 no matching rule -> dropped at egress (default DROP) |
| 10 | + app[3] 1003->2003 AH-protected -> delivered (egress AH PROTECT, ingress ACCEPT AH) |
| 11 | + |
| 12 | +The AH stream is the point of this test: the AH ingress path had a latent |
| 13 | +double-remove bug (it removed the IPsecAuthenticationHeader twice, so the second |
| 14 | +removeAtFront<> hit the following EncryptedChunk and crashed). No prior example used |
| 15 | +AH, so neither a fingerprint nor the existing examples could have caught it. Here we |
| 16 | +require an AH datagram to be de-protected and delivered end to end. |
| 17 | + |
| 18 | +%#-------------------------------------------------------------------------------------------------------------- |
| 19 | +%file: test.ned |
| 20 | +import inet.networklayer.configurator.ipv6.Ipv6NetworkConfigurator; |
| 21 | +import inet.node.ipv6.StandardHost6; |
| 22 | +import ned.DatarateChannel; |
| 23 | + |
| 24 | +network IPsecIpv6Test |
| 25 | +{ |
| 26 | + submodules: |
| 27 | + client1: StandardHost6 { @display("p=80,100;i=device/pc3"); } |
| 28 | + server: StandardHost6 { @display("p=280,100;i=device/pc2"); } |
| 29 | + configurator: Ipv6NetworkConfigurator { @display("p=80,180"); } |
| 30 | + connections: |
| 31 | + client1.pppg++ <--> { datarate = 10Mbps; delay = 0.1us; } <--> server.pppg++; |
| 32 | +} |
| 33 | + |
| 34 | +%#-------------------------------------------------------------------------------------------------------------- |
| 35 | +%file: ipsecConfig.xml |
| 36 | +<ipsecConfig> |
| 37 | + <Devices> |
| 38 | + <Device id="client1"> |
| 39 | + <!-- app[0] 1000->2000 UDP: ESP --> |
| 40 | + <SecurityPolicy> |
| 41 | + <Selector> |
| 42 | + <LocalAddress>client1</LocalAddress> |
| 43 | + <RemoteAddress>server</RemoteAddress> |
| 44 | + <Protocol>UDP</Protocol> |
| 45 | + <LocalPort>1000</LocalPort> |
| 46 | + <RemotePort>2000</RemotePort> |
| 47 | + </Selector> |
| 48 | + <Direction>OUT</Direction> |
| 49 | + <Action>PROTECT</Action> |
| 50 | + <Protection>ESP</Protection> |
| 51 | + <EspMode>CONFIDENTIALITY</EspMode> |
| 52 | + <EncryptionAlg>AES_CBC_128</EncryptionAlg> |
| 53 | + <SecurityAssociation><SPI>101</SPI></SecurityAssociation> |
| 54 | + </SecurityPolicy> |
| 55 | + |
| 56 | + <!-- app[1] 1001->2001 UDP: BYPASS --> |
| 57 | + <SecurityPolicy> |
| 58 | + <Selector> |
| 59 | + <LocalAddress>client1</LocalAddress> |
| 60 | + <RemoteAddress>server</RemoteAddress> |
| 61 | + <Protocol>UDP</Protocol> |
| 62 | + <LocalPort>1001</LocalPort> |
| 63 | + <RemotePort>2001</RemotePort> |
| 64 | + </Selector> |
| 65 | + <Direction>OUT</Direction> |
| 66 | + <Action>BYPASS</Action> |
| 67 | + </SecurityPolicy> |
| 68 | + |
| 69 | + <!-- app[3] 1003->2003 UDP: AH --> |
| 70 | + <SecurityPolicy> |
| 71 | + <Selector> |
| 72 | + <LocalAddress>client1</LocalAddress> |
| 73 | + <RemoteAddress>server</RemoteAddress> |
| 74 | + <Protocol>UDP</Protocol> |
| 75 | + <LocalPort>1003</LocalPort> |
| 76 | + <RemotePort>2003</RemotePort> |
| 77 | + </Selector> |
| 78 | + <Direction>OUT</Direction> |
| 79 | + <Action>PROTECT</Action> |
| 80 | + <Protection>AH</Protection> |
| 81 | + <AuthenticationAlg>HMAC_SHA1</AuthenticationAlg> |
| 82 | + <SecurityAssociation><SPI>103</SPI></SecurityAssociation> |
| 83 | + </SecurityPolicy> |
| 84 | + |
| 85 | + <!-- app[2] 1002->2002 has NO policy => default DROP at egress --> |
| 86 | + </Device> |
| 87 | + |
| 88 | + <Device id="server"> |
| 89 | + <!-- app[0] 2000<-1000 UDP: ESP, same SPI as client1's OUT rule --> |
| 90 | + <SecurityPolicy> |
| 91 | + <Selector> |
| 92 | + <LocalAddress>server</LocalAddress> |
| 93 | + <RemoteAddress>client1</RemoteAddress> |
| 94 | + <Protocol>UDP</Protocol> |
| 95 | + <LocalPort>2000</LocalPort> |
| 96 | + <RemotePort>1000</RemotePort> |
| 97 | + </Selector> |
| 98 | + <Direction>IN</Direction> |
| 99 | + <Action>PROTECT</Action> |
| 100 | + <Protection>ESP</Protection> |
| 101 | + <EspMode>CONFIDENTIALITY</EspMode> |
| 102 | + <EncryptionAlg>AES_CBC_128</EncryptionAlg> |
| 103 | + <SecurityAssociation><SPI>101</SPI></SecurityAssociation> |
| 104 | + </SecurityPolicy> |
| 105 | + |
| 106 | + <!-- app[1] 2001<-1001 UDP: BYPASS --> |
| 107 | + <SecurityPolicy> |
| 108 | + <Selector> |
| 109 | + <LocalAddress>server</LocalAddress> |
| 110 | + <RemoteAddress>client1</RemoteAddress> |
| 111 | + <Protocol>UDP</Protocol> |
| 112 | + <LocalPort>2001</LocalPort> |
| 113 | + <RemotePort>1001</RemotePort> |
| 114 | + </Selector> |
| 115 | + <Direction>IN</Direction> |
| 116 | + <Action>BYPASS</Action> |
| 117 | + </SecurityPolicy> |
| 118 | + |
| 119 | + <!-- app[3] 2003<-1003 UDP: AH, same SPI as client1's OUT rule --> |
| 120 | + <SecurityPolicy> |
| 121 | + <Selector> |
| 122 | + <LocalAddress>server</LocalAddress> |
| 123 | + <RemoteAddress>client1</RemoteAddress> |
| 124 | + <Protocol>UDP</Protocol> |
| 125 | + <LocalPort>2003</LocalPort> |
| 126 | + <RemotePort>1003</RemotePort> |
| 127 | + </Selector> |
| 128 | + <Direction>IN</Direction> |
| 129 | + <Action>PROTECT</Action> |
| 130 | + <Protection>AH</Protection> |
| 131 | + <AuthenticationAlg>HMAC_SHA1</AuthenticationAlg> |
| 132 | + <SecurityAssociation><SPI>103</SPI></SecurityAssociation> |
| 133 | + </SecurityPolicy> |
| 134 | + </Device> |
| 135 | + </Devices> |
| 136 | +</ipsecConfig> |
| 137 | + |
| 138 | +%#-------------------------------------------------------------------------------------------------------------- |
| 139 | +%inifile: omnetpp.ini |
| 140 | +[General] |
| 141 | +ned-path = .;../../../../src;../../lib |
| 142 | +network = IPsecIpv6Test |
| 143 | +sim-time-limit = 10s |
| 144 | +cmdenv-express-mode = false |
| 145 | +cmdenv-log-prefix = "%C: " |
| 146 | + |
| 147 | +# static global IPv6 addresses so "client1"/"server" in the SPD selectors resolve to |
| 148 | +# routable addresses (wire each node's Ipv6NodeConfigurator to the global configurator) |
| 149 | +**.ipv6.configurator.networkConfiguratorModule = "configurator" |
| 150 | + |
| 151 | +**.client*.**.hasIpsec = true |
| 152 | +**.server.**.hasIpsec = true |
| 153 | +**.client1.**spdConfig = xmldoc("ipsecConfig.xml", "ipsecConfig/Devices/Device[@id='client1']/") |
| 154 | +**.server.**spdConfig = xmldoc("ipsecConfig.xml", "ipsecConfig/Devices/Device[@id='server']/") |
| 155 | + |
| 156 | +# zero delays -> deterministic ACCEPT path (the QUEUE/reinject path is covered by the |
| 157 | +# ipv6.ini example and NetfilterHooks_Ipv6 test) |
| 158 | +**.ipsec.ahProtectOutDelay = 0s |
| 159 | +**.ipsec.ahProtectInDelay = 0s |
| 160 | +**.ipsec.espProtectOutDelay = 0s |
| 161 | +**.ipsec.espProtectInDelay = 0s |
| 162 | + |
| 163 | +**.numApps = 4 |
| 164 | +**.client1.app[*].typename = "UdpBasicApp" |
| 165 | +**.client1.app[0].localPort = 1000 |
| 166 | +**.client1.app[1].localPort = 1001 |
| 167 | +**.client1.app[2].localPort = 1002 |
| 168 | +**.client1.app[3].localPort = 1003 |
| 169 | +**.client1.app[*].destAddresses = "server" |
| 170 | +**.client1.app[0].destPort = 2000 |
| 171 | +**.client1.app[1].destPort = 2001 |
| 172 | +**.client1.app[2].destPort = 2002 |
| 173 | +**.client1.app[3].destPort = 2003 |
| 174 | +**.client1.app[*].startTime = 1s |
| 175 | +**.client1.app[*].stopTime = 4s |
| 176 | +**.client1.app[*].sendInterval = 1s |
| 177 | +**.client1.app[*].messageLength = 100B |
| 178 | + |
| 179 | +**.server.app[*].typename = "UdpSink" |
| 180 | +**.server.app[0].localPort = 2000 |
| 181 | +**.server.app[1].localPort = 2001 |
| 182 | +**.server.app[2].localPort = 2002 |
| 183 | +**.server.app[3].localPort = 2003 |
| 184 | + |
| 185 | +%#-------------------------------------------------------------------------------------------------------------- |
| 186 | +%# ===== egress decisions on client1 ===== |
| 187 | +%contains: stdout |
| 188 | +IPsec OUT ESP PROTECT |
| 189 | +%contains: stdout |
| 190 | +IPsec OUT AH PROTECT |
| 191 | +%contains: stdout |
| 192 | +IPsec OUT BYPASS rule |
| 193 | +%# app[2] has no policy -> default DROP at egress |
| 194 | +%contains: stdout |
| 195 | +IPsec OUT BYPASS, no matching rule |
| 196 | +%# ===== ingress decisions on server ===== |
| 197 | +%contains: stdout |
| 198 | +IPsec IN ACCEPT ESP |
| 199 | +%# the AH de-protection that the double-remove fix unlocks: |
| 200 | +%contains: stdout |
| 201 | +IPsec IN ACCEPT AH |
| 202 | +%contains: stdout |
| 203 | +IPsec BYPASS rule |
| 204 | +%# ===== end-to-end delivery: ESP, BYPASS and AH streams arrive; the no-rule stream does not ===== |
| 205 | +%contains: stdout |
| 206 | +server.app[0]: Received packet |
| 207 | +%contains: stdout |
| 208 | +server.app[1]: Received packet |
| 209 | +%contains: stdout |
| 210 | +server.app[3]: Received packet |
| 211 | +%not-contains: stdout |
| 212 | +server.app[2]: Received packet |
| 213 | +%#-------------------------------------------------------------------------------------------------------------- |
| 214 | +%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true |
| 215 | +%not-contains: test_undisposed.out |
| 216 | +undisposed object: ( |
| 217 | +%#-------------------------------------------------------------------------------------------------------------- |
0 commit comments