📄 routing.txt
字号:
Routing and Erouting in Pluto=============================RCSID $Id: routing.txt,v 1.5 2002/04/24 07:35:58 mcr Exp $This is meant as internal documentation for Pluto. As such, itpresumes some understanding of Pluto's code.It also describes KLIPS 1 erouting, including details not otherwisedocumented. KLIPS 1 documentation would be better included in KLIPS.Routing and erouting are complicated enough that the Pluto code needsa guide. This document is meant to be that guide.Mechanisms available to Pluto-----------------------------All outbound packets that are to be processed by KLIPS 1 must berouted to an ipsecN network interface. Pluto only uses normal routing(as opposed to "Advanced Routing"), so the selection of packets ismade solely on the basis of the destination address. (Since theactual routing commands are in the updown script, they could bechanged by the administrator, but Pluto needs to understand what isgoing on, and it currently assumes normal routing is used.)When an outbound packet hits an ipsecN interface, KLIPS figures outhow to process it by finding an eroute that applies to the source anddestination addresses. Eroutes are global: they are not specific to aparticular ipsecN interface (routing needs to get the packets to anyipsecN interface; erouting takes it from there, ignoring issues ofsource IP address and nexthop (because nobody knows!)). If multipleeroutes apply to the packet, among the ones with the most specificsource subnet, the one with the most specific destination subset ischosen (RGB thinks). If no eroute is discovered, KLIPS acts as if itwas covered by a DROP eroute (this is the default behaviour; it can bechanged). At most one eroute can exist for a particular pair ofclient subnets.There are fundamentally two kinds of eroutes: "shunt" eroutes and onesthat specify that a packet is to be processed by a group of IPSEC SAs.Shunt eroutes specify what is to be done with the packet. Rememberthat these only apply to outbound packets.- TRAP: notify Pluto of the packet (presumably to attempt to negotiate an appropriate group of IPSEC SAs). At the same time, KLIPS installs a HOLD shunt (see below) for the specific source and destination addresses from the packet and retains the packet for later reprocessing (KLIPS does not yet implement retention). Beware: if the TRAP's subnets both contained a single IP address then installing the HOLD would actually delete the TRAP.- PASS: let the packet through in the clear- DROP: discard the packet- REJECT: discard the packet and notify the sender- HOLD: (automatically created by KLIPS when a TRAP fires) block the packet, but retain it. If there is already a retained packet, drop the old one and retain the new. When the HOLD shunt is deleted or replaced, the retained packet is reinjected -- there might now be a tunnel. Note that KLIPS doesn't yet implement the retention part, so HOLD is really like a DROP.One consequence of there being only one eroute for a pair of clientsis that KLIPS will only use one SA group for output for this pair,even though there could be several SA groups that are authorised andlive. Pluto chooses to make this the youngest such group.KLIPS lets through in the clear outbound UDP/500 packets that wouldotherwise be processed if they originate on this host and meet certainother conditions. The actual test is source == me && (no_eroute || dest == eroute.dest || isanyaddr(eroute.dest)) && port == UDP/500The idea is that IKE packets between us and a peer should not besent through an IPSEC tunnel negotiated between us. Furthermore,our shunt eroutes should not apply to our IKE packets (shunt erouteswill generally have an eroute.dest of 0.0.0.0 or its IPv6 equivalent).Inbound behaviour is controlled in a quite different way. KLIPSprocesses only those inbound packets of ESP or AH protocol, with adestination address for this machine's ipsecN interfaces. Theprocessing is as dictated by the SAs involved. Unfortunately, thedecapsulated packet's source and destination address are not checked(part of "inbound policy checking").To prevent clear packets being accepted, firewall rules must be put inplace. This has nothing to do with KLIPS, but is nonetheless inimportant part of security. It isn't clear what firewalling makessense when Opportunism is allowed.For routing and firewalling, Pluto invokes the updown script. Plutoinstalls eroutes via extended PF_KEY messages.Current Pluto Behaviour-----------------------Data Structures:Routes and most eroutes are associated with connections (structconnection, a potential connection description). The enum routing_tfield "routing" in struct connection records the state of routing anderouting for that connection. The values are: RT_UNROUTED, /* unrouted */ RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */ RT_ROUTED_PROSPECTIVE, /* routed, and TRAP shunt installed */ RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */ RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */ RT_ROUTED_TUNNEL /* routed, and erouted to an IPSEC SA group */Notice that the routing and erouting are not independent: erouting(except for HOLD) implies that the connection is routed.Several struct connections may have the same destination subnet. Ifthey agree on what the route should be, they can share it -- any ofthem may have routing >= RT_ROUTED_PROSPECTIVE. If they disagree,they cannot simultaneously be routed.invariant: for all struct connections c, d: (c.that.client == d.that.client && c.routing >= RT_ROUTED_PROSPECTIVE && d.routing >= RT_ROUTED_PROSPECTIVE) => c.interface == d.interface && c.this.nexthop == d.this.nexthopThere are two kinds of eroutes: shunt eroutes and ones for an IPSEC SAGroup. Most eroutes are associated with and are represeented in aconnection. The exception is that some HOLD and PASS shunts do notcorrespond to connections; those are represented in the bare_shunttable.An eroute for an IPSEC SA Group is associated with the state objectfor that Group. The existence of such an eroute is also representedby the "so_serial_t eroute_owner" field in the struct connection. Thevalue is the serial number of the state object for the Group. Thespecial value SOS_NOBODY means that there is no owner associated withthis connection for the eroute and hence no normal eroute. At mostone eroute owner may exist for a particular (source subnet,destination subnet) pair. A Pluto-managed eroute cannot be associatedwith an RT_UNROUTED connection.invariant: for all struct connection c: c.routing == RT_EROUTED_TUNNEL || c.eroute_owner == SOS_NOBODYinvariant: for all struct connections c, d: c.this.client == d.this.client && c.that.client == d.that.client && &c != &d => c.routing == RT_UNROUTED || d.routing == RT_UNROUTEDIf no normal eroute is set for a particular (source subnet,destination subnet) pair for which a connection is routed, then ashunt eroute would have been installed. This specifies what shouldhappen to packets snared by the route.When Pluto is notified by KLIPS of a packet that has been TRAPped,there is no connection with which to associate the HOLD. It istemporarily held in the "bare_shunt table". If Opportunism isattempted but DNS doesn't provide Security Gateway information, Plutowill replace the HOLD with a PASS shunt. Since this PASS isn'tassociated with a connection, it too will reside in the bare_shunttable. If the HOLD can be associated with a connection, it will beremoved from the bare_shunt table and represented in the connection.There are two contexts for which shunt eroutes are installed by Plutofor a particular connection. The first context is with the prospectof dealing with packets before any negotiation has been attempted. Icall this context "prospective". Currently is a TRAP shunt, used tocatch packets for initiate opportunistic negotiation. In the future,it might also be used to implement preordained PASS, DROP, or REJECTrules.The second context is after a failed negotiation. I call this context"failure". At this point a different kind of shunt eroute isappropriate. Depending on policy, it could be PASS, DROP, or REJECT,but it is unlikely to be TRAP. The shunt eroute should have alifetime (this isn't yet implemented). When the lifetime expires, thefailure shunt eroute should be replaced by the prospective shunteroute.The kind and duration of a failure shunt eroute should perhaps dependon the nature of the failure, at least as imperfectly detected byPluto. We haven't looked at this. In particular, the mapping fromobservations to robust respose isn't obvious.The shunt eroute policies should be a function of the potentialconnection. The failure shunt eroute can be specified for aparticular connection with the flags --pass and --drop in a connectiondefinition. There are four combinations, and each has a distinctmeaning. The failure shunt eroute is incompletely implemented andcannot be represented in /etc/ipsec.conf.There is as yet no control over the prospective shunt eroute: it isalways TRAP as far as Pluto is concerned. This is probablyreasonable: any other fate suggests that no negotiation will be done,and so a connection definition is inappropriate. These should beimplemented as manual conns. There remains the issue of whether Plutoshould be aware of them -- currently it is not.Routines:[in kernel.c]bool do_command(struct connection *c, const char *verb) Run the updown script to perform such tasks as installing a route and adjust the firewall.bool could_route(struct connection *c) Check to see whether we could route and eroute the connection. <- shunt_eroute_connection (to check if --route can be performed) <- install_inbound_ipsec_sa (to see if it will be possible to (later) install route and eroute the corresponding outbound SA) <- install_ipsec_sa (to see if the outbound SA can be routed and erouted)bool trap_connection(struct connection *c) Install a TRAP shunt eroute for this connection. This implements "whack --route", the way an admin can specify that packets for a connection should be caught without first bringing it up.void unroute_connection(struct connection *c) Delete any eroute for a connection and unroute it if route isn't shared. <- release_connection <- whack_handle (for "whack --unroute)bool eroute_connection(struct connection *c, ipsec_spi_t spi, unsigned int proto, unsigned int satype, unsigned int op, const char *opname UNUSED) Issue PF_KEY commands to KLIPS to add, replace, or delete an eroute. The verb is specified by op and described (for logging) by opname. <- assign_hold <- sag_eroute <- shunt_eroutebool assign_hold(struct connection *c, const ip_address *src, const ip_address *dst) Take a HOLD from the bare_shunt table and assign it to a connection. If the HOLD is broadened (i.e. the connection's source or destination subnets contain more than one IP address), this will involve replacing the HOLD with a different one.bool sag_eroute(struct state *st, unsigned op, const char *opname) SA Group eroute manipulation. The SA Group concerned is identified with a state object. <- route_and_eroute several timesbool shunt_eroute(struct connection *c, unsigned int op, const char *opname) shunt eroute manipulation. Shunt eroutes are associated with connections. <- unroute_connection <- route_and_eroute <- delete_ipsec_sabool route_and_eroute(struct connection *c, struct state *st) Install a route and then a prospective shunt eroute or an SA group eroute. The code assumes that could_route had previously given the go-ahead. Any SA group to be erouted must already exist. <- shunt_eroute_connection <- install_ipsec_savoid scan_proc_shunts(void) Every SHUNT_SCAN_INTERVAL scan /proc/net/ipsec_eroute. Delete any PASS eroute in the bare_shunt table that hasn't been used within the last SHUNT_PATIENCE seconds. For any HOLD for which Pluto hasn't received an ACQUIRE (possibly lost due to congestion), act as if an ACQUIRE were received.[in connection.c]struct connection *route_owner(struct connection *c, struct connection **erop) Find the connection to connection c's peer's client with the largest value of .routing. All other things being equal, preference is given to c. Return NULL if no connection is routed at all. If erop is non-null, sets it to a connection sharing both our client subnet and peer's client subnet with the largest value of .routing. The return value is used to find other connections sharing a route. The value of *erop is used to find other connections sharing an eroute. <- could_route (to find any conflicting routes or eroutes) <- unroute_connection (to find out if our route is still in use after this connection is finished with it) <- install_inbound_ipsec_sa (to find other IPSEC SAs for the same peer clients; when we find them WE KILL THEM; a kludge to deal with road warriors reconnecting) <- route_and_eroute (to find all the connections from which the route or eroute is being stolen)Uses:- setting up route & shunt eroute to TRAP packets for opportunism (whack --route). Perhaps also manually designating DROP, REJECT, or PASS for certain packets. whack_handle() responds to --route; calls route_connection()- removing same (whack --unroute) whack_handle() responds to --unroute; calls unroute_connection()- installing route & normal eroute for a newly negotiated group of outbound IPSEC SAs + perhaps an (additional) route is not needed: if the negotiation was initiated by a TRAPped outgoing packet, then there must already have been a route that got the packet to ipsecN. Mind you, it could have been the wrong N! install_ipsec_sa()- updating a normal eroute when a new group of IPSEC SAs replaces an old one due to rekeying. install_ipsec_sa()- replacing an old eroute when a negotiation fails. But this is tricky. If this was a rekeying, we should just leave the old normal eroute be -- it might still work. Otherwise, this was an initial negotiation: we should replace the shunt eroute with one appropriate for the failure context.- when a group of IPSEC SAs dies or is killed, and it had the eroute, its normal eroute should be replaced by a shunt eroute. If there was an attempt to replace the group, the replacement is in the failure context; otherwise the replacement is in the prospective context.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -