Skip to content

ipsec: fix: emit packetDropped for the datagrams IPsec discards - #1362

Open
adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ipsec-packet-dropped
Open

adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ipsec-packet-dropped

Conversation

@adamgeorge309

Copy link
Copy Markdown
Contributor

The IP Security (IPsec) module discarded datagrams without emitting packetDropped, so PacketDropVisualizer and the statistics built on that signal did not see a Security Policy Database (SPD) DISCARD or any other IPsec discard. IPsec now emits packetDropped at each discard that it counts, and IPsec.ned records two per-reason statistics.

Risk: low. Only signal emissions and statistics are added; no datagram is routed, delayed or deleted differently, and no fingerprint changes. In models with IPsec discards, packetDropped listeners and PacketDropVisualizer now see them, and every IPsec module records new scalars.

Closes #1361

One commit: ipsec: fix: emit packetDropped for the datagrams IPsec discards.

The problem

IPsec.cc on master bba1db4c81 returns INetfilter::IHook::DROP at 14 sites after emitting outDrop, inUnprotectedDrop or inProtectedDrop, which are long counter signals. The Ipv4 and Ipv6 hook dispatchers then delete the datagram (case INetfilter::IHook::DROP: delete packet;). Neither side emits packetDropped, and IPsec.ned does not declare it.

The change

  • IPsec::emitPacketDropped(Packet *, PacketDropReason), a new private member function, emits packetDropped with a PacketDropDetails reason. The packet is still alive at that point; the network layer deletes it after the hook returns.
  • Each of the 14 counted discard sites calls it immediately before its counter emission: LIFETIME_EXPIRED where an inbound packet arrives on a Security Association (SA) whose hard lifetime has ended or whose byte limit the packet would exceed (one site each for the Authentication Header (AH) and the Encapsulating Security Payload (ESP)), OTHER_PACKET_DROP at the other 12. An outbound datagram whose only matching SA has expired is skipped by protectDatagram()'s SA loop and reaches the "no SA of the PROTECT entry matches" site, so it is reported as OTHER_PACKET_DROP. No PacketDropReason describes a policy discard, so those use OTHER_PACKET_DROP.
  • The discard of an ESP dummy packet (IPsec.cc:1040-1042 on master) stays silent. Request for Comments (RFC) 4303 Section 2.6 has the receiver discard a dummy packet as normal operation, and it has no counter either.
  • IPsec.ned: @signal[packetDropped](type=inet::Packet), and @statistic[packetDropLifetimeExpired] and @statistic[packetDropUndefined], written as in Ipv4.ned.

At six inbound AH and ESP sites, removeNetworkHeader() has already run. Where the AH or ESP header is still at hand (the SA does not prescribe the protocol, or no SA has the Security Parameters Index (SPI)), the AH or ESP header and the network header are inserted back, which gives the datagram as received, or as AH processing gave it back when AH covers ESP. At the two lifetime sites, the network header is completed and inserted as on the accept path (setNetworkHeaderProtocol(), updateNetworkHeaderLength()), which gives the datagram as AH or ESP processing returns it. A listener that dissects the emitted packet therefore finds a network header at its front. In the new test, the six datagrams the server drops sum to 852 bytes, the bytes its Point-to-Point Protocol (PPP) interface received (894) minus 7 bytes of PPP framing each.

LIFETIME_EXPIRED elsewhere in INET means that the packet's own lifetime has ended; here it means that the SA's lifetime has, which RFC 4301 Section 4.4.2.1 also calls a lifetime.

No C++ interface outside IPsec, Network Description (NED) parameter, message field or feature descriptor changes.

Not addressed here: the log text "IPsec OUT BYPASS, no matching rule" at the outbound site with no matching SPD entry, which discards; other netfilter hooks that return DROP without emitting packetDropped (CloudDelayerBase, Gpsr, Mipv6, SctpNatHook).

Verification

Release build (make MODE=release in the root and tests/module/lib), each suite run on master bba1db4c81 and with this change.

New module test tests/module/IPsec_packet_dropped.test: two StandardHosts with hasIpsec = true. The client's SPD has an OUT entry with the action DISCARD for User Datagram Protocol (UDP) datagrams to port 2000 and an OUT entry with the action BYPASS for port 2001; the server's SPD is empty. A third OUT entry protects UDP traffic to port 2002 with ESP under SPI 7, for which the server has no SA. The client sends three datagrams to each port. The test checks that client.ipv4.ipsec records outDrop:count 3 and packetDropUndefined:count 3, and server.ipv4.ipsec records inUnprotectedDrop:count 3, inProtectedDrop:count 3 ("IPsec IN DROP ESP, no matching rule", one of the six sites above) and packetDropUndefined:count 6. On master's source, the same counters are 3 and packetDropUndefined does not exist, so the test fails.

Command Master This change
tests/fingerprint: ./fingerprinttest -s -F tyf 1774 run, 5 failures, 62 errors, 1 expected error the same failing and erroring rows, with the same computed fingerprints
tests/module: inet_run_module_tests -m release --no-build -l ERROR 657 run, 368 pass, 289 fail 658 run, 370 pass, 288 fail: the new test passes, and the same tests fail by name except Ieee80211BlockAckVariant_1 (below)

Of the 289 module failures on master, 274 are tcp_* tests and 15 are ConvolutionalCoder12, ConvolutionalCoder34, DimensionalMediumAnalogModel_PrintAttenuation_1, EtherHost_lifecycle, ExternalProcess_3, Ieee80211BitDomain, Ieee80211BlockAckVariant_1, Ieee80211SymbolDomain, Ieee8021d-Rstp, Ieee8021d-Stp, IPv6_packet_too_big, LogNormalShadowing_Correlated_4, MIPv6_tcp_handover, PacketGate_1, UDPSocket_1. The 5 fingerprint failures are rows of mipv6-refactoring.csv whose recorded ~tNlb fingerprints are stale on master; the 62 errors are configurations whose optional features are not built.

Ieee80211BlockAckVariant_1 runs a debug build of INET (check-profile.py) and fails with "INET debug executable or shared library not found" where there is none. The worktree of this change has a debug build from earlier work and the master worktree does not; the test does not involve IPsec.

Statistical baselines (statistics repository, origin/master): the six examples/inet/ipsec baselines gain the new scalars. In both omnetpp.ini and ipv6.ini, client1 records outDrop counts of 40 and 7, which the new packetDropUndefined counts too. They need re-recording after merge.

Gates: check-pull-request.sh --base origin/master (commits, classification, includes, NED parameters, description), check-source-seals.sh --base origin/master and check-architecture.sh src/inet/networklayer/ipsec pass.

Relationship to other pull requests

IPsec discarded a datagram by returning DROP from its netfilter hook after emitting only its own counter signals (outDrop, inUnprotectedDrop, inProtectedDrop), and the network layer deleted the datagram without emitting packetDropped either. PacketDropVisualizer, which subscribes to packetDropped, and the statistics and result filters built on it did not see Security Policy Database (SPD) discards or any other IPsec discard.

A new member function, emitPacketDropped(), emits packetDropped with a PacketDropDetails reason, and each of the 14 sites that count a discard calls it before returning DROP: with LIFETIME_EXPIRED for the two inbound sites where the hard lifetime of the Security Association has ended or the packet would exceed its byte limit, and with OTHER_PACKET_DROP for the others, including an outbound datagram whose only Security Association has expired. At the six inbound Authentication Header (AH) and Encapsulating Security Payload (ESP) sites that have already removed the network header, the datagram is restored before the emit: as it reached AH or ESP processing where the AH or ESP header is still at hand (as received, unless AH covered ESP), and as AH or ESP processing gives it back at the two lifetime sites. The discard of an ESP dummy packet stays silent, because Request for Comments (RFC) 4303 Section 2.6 makes it normal operation. IPsec.ned declares the signal and records packetDropLifetimeExpired and packetDropUndefined, like Ipv4.ned.

tests/module/IPsec_packet_dropped.test discards three datagrams by an outbound SPD DISCARD entry at the client, and at the server three unprotected datagrams that no inbound SPD entry matches and three ESP-protected datagrams whose Security Parameters Index (SPI) has no Security Association, and checks that packetDropUndefined counts each IPsec module's outDrop, inUnprotectedDrop and inProtectedDrop discards.

No fingerprint changes. The statistical baselines of examples/inet/ipsec gain the new scalars.

Change: src.networklayer.ipsec.IPsec | behavior.change.fix | test statistical whatsnew

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ipsec: an IPsec discard emits no packetDropped, so PacketDropVisualizer and drop statistics miss it

1 participant