天天看點

Pluto中的路由和erouting機制

做Strongswan測試的時候,我發現strongswan不能為同一個目的網絡建立起多條隧道,百思不得其解,最後在pluto的man手冊裡找到了答案,裡面鄭重聲明pluto不支援相同目标網絡而不同隧道,即使是擁有不同的IP或裝置接口。但同樣使用pluto做IKE daemon的openswan對待這種情況的政策卻比較寬松,在其比較靠後的版本裡,預設支援不同裝置+IP到同一目标網絡(通常配置為rightsubnet)的多條隧道。Pluto 的路由政策都在兩者的codebase中指定,路徑為:/openswan-x.x.x/programs/pluto/kernel.c ,  或者/strongswan-x.x.x/src/pluto/kernel.c , 有興趣的朋友可以研究下。相關内容如下:

>>  /* If there is already a route for peer's client subnet

>>   * and it disagrees about interface or nexthop, we cannot steal it.

>>   * Note: if this connection is already routed (perhaps for another

>>   * state object), the route will agree.

>>   * This is as it should be -- it will arise during rekeying.

>>   */

>>  if (ro != NULL && !routes_agree(ro, c))

>>  {

>>   loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""

>>    , ro->name);

>>   return route_impossible;  /* another connection already

>>           using the eroute */

>>  }

貌似國内網站上對*swan的讨論比較少,有也隻是一些基本安裝配置,其實那些硬體防火牆和路由器的實作好多都是以swan的代碼為基礎的,swan們的功能是相當強大的,我們國内的東東基本就是把那些現成的代碼複制過來再稍加修改的。呵呵。這次來學習下pluto的路由機制吧。

    1 Routing and Erouting in Pluto

    2 =============================

    3 

    4 This is meant as internal documentation for Pluto.  As such, it

    5 presumes some understanding of Pluto's code.

    6 

    7 It also describes KLIPS 1 erouting, including details not otherwise

    8 documented.  KLIPS 1 documentation would be better included in KLIPS.

    9 

   10 Routing and erouting are complicated enough that the Pluto code needs

   11 a guide.  This document is meant to be that guide.

   12 

   13 

   14 Mechanisms available to Pluto

   15 -----------------------------

   16 

   17 All outbound packets that are to be processed by KLIPS 1 must be

   18 routed to an ipsecN network interface.  Pluto only uses normal routing

   19 (as opposed to "Advanced Routing"), so the selection of packets is

   20 made solely on the basis of the destination address.  (Since the

   21 actual routing commands are in the updown script, they could be

   22 changed by the administrator, but Pluto needs to understand what is

   23 going on, and it currently assumes normal routing is used.)

   24 

   25 When an outbound packet hits an ipsecN interface, KLIPS figures out

   26 how to process it by finding an eroute that applies to the source and

   27 destination addresses.  Eroutes are global: they are not specific to a

   28 particular ipsecN interface (routing needs to get the packets to any

   29 ipsecN interface; erouting takes it from there, ignoring issues of

   30 source IP address and nexthop (because nobody knows!)).  If multiple

   31 eroutes apply to the packet, among the ones with the most specific

   32 source subnet, the one with the most specific destination subset is

   33 chosen (RGB thinks).  If no eroute is discovered, KLIPS acts as if it

   34 was covered by a DROP eroute (this is the default behaviour; it can be

   35 changed).  At most one eroute can exist for a particular pair of

   36 client subnets.

   37 

   38 There are fundamentally two kinds of eroutes: "shunt" eroutes and ones

   39 that specify that a packet is to be processed by a group of IPSEC SAs.

   40 Shunt eroutes specify what is to be done with the packet.  Remember

   41 that these only apply to outbound packets.

   42 

   43 - TRAP: notify Pluto of the packet (presumably to attempt to negotiate

   44   an appropriate group of IPSEC SAs).  At the same time, KLIPS

   45   installs a HOLD shunt (see below) for the specific source and

   46   destination addresses from the packet and retains the packet

   47   for later reprocessing (KLIPS does not yet implement retention).

   48   Beware: if the TRAP's subnets both contained a single IP address

   49   then installing the HOLD would actually delete the TRAP.

   50 

   51 - PASS: let the packet through in the clear

   52 

   53 - DROP: discard the packet

   54 

   55 - REJECT: discard the packet and notify the sender

   56 

   57 - HOLD: (automatically created by KLIPS when a TRAP fires) block

   58   the packet, but retain it.  If there is already a retained

   59   packet, drop the old one and retain the new.  When the HOLD

   60   shunt is deleted or replaced, the retained packet is reinjected --

   61   there might now be a tunnel.  Note that KLIPS doesn't yet

   62   implement the retention part, so HOLD is really like a DROP.

   63 

   64 One consequence of there being only one eroute for a pair of clients

   65 is that KLIPS will only use one SA group for output for this pair,

   66 even though there could be several SA groups that are authorised and

   67 live.  Pluto chooses to make this the youngest such group.

   68 

   69 

   70 

   71 KLIPS lets through in the clear outbound UDP/500 packets that would

   72 otherwise be processed if they originate on this host and meet certain

   73 other conditions.  The actual test is

   74     source == me

   75     && (no_eroute || dest == eroute.dest || isanyaddr(eroute.dest))

   76     && port == UDP/500

   77 The idea is that IKE packets between us and a peer should not be

   78 sent through an IPSEC tunnel negotiated between us.  Furthermore,

   79 our shunt eroutes should not apply to our IKE packets (shunt eroutes

   80 will generally have an eroute.dest of 0.0.0.0 or its IPv6 equivalent).

   81 

   82 Inbound behaviour is controlled in a quite different way.  KLIPS

   83 processes only those inbound packets of ESP or AH protocol, with a

   84 destination address for this machine's ipsecN interfaces. The

   85 processing is as dictated by the SAs involved.  Unfortunately, the

   86 decapsulated packet's source and destination address are not checked

   87 (part of "inbound policy checking").

   88 

   89 To prevent clear packets being accepted, firewall rules must be put in

   90 place.  This has nothing to do with KLIPS, but is nonetheless in

   91 important part of security.  It isn't clear what firewalling makes

   92 sense when Opportunism is allowed.

   93 

   94 

   95 For routing and firewalling, Pluto invokes the updown script.  Pluto

   96 installs eroutes via extended PF_KEY messages.

   97 

   98 

   99 Current Pluto Behaviour

  100 -----------------------

  101 

  102 Data Structures:

  103 

  104 Routes and most eroutes are associated with connections (struct

  105 connection, a potential connection description).  The enum routing_t

  106 field "routing" in struct connection records the state of routing and

  107 erouting for that connection.  The values are:

  108     RT_UNROUTED,    /* unrouted */

  109     RT_UNROUTED_HOLD,    /* unrouted, but HOLD shunt installed */

  110     RT_ROUTED_PROSPECTIVE,    /* routed, and TRAP shunt installed */

  111     RT_ROUTED_HOLD,    /* routed, and HOLD shunt installed */

  112     RT_ROUTED_FAILURE,    /* routed, and failure-context shunt installed */

  113     RT_ROUTED_TUNNEL    /* routed, and erouted to an IPSEC SA group */

  114 Notice that the routing and erouting are not independent: erouting

  115 (except for HOLD) implies that the connection is routed.

  116 

  117 Several struct connections may have the same destination subnet.  If

  118 they agree on what the route should be, they can share it -- any of

  119 them may have routing >= RT_ROUTED_PROSPECTIVE.  If they disagree,

  120 they cannot simultaneously be routed.

  121 

  122 invariant: for all struct connections c, d:

  123     (c.that.client == d.that.client

  124         && c.routing >= RT_ROUTED_PROSPECTIVE

  125         && d.routing >= RT_ROUTED_PROSPECTIVE)

  126     => c.interface == d.interface && c.this.nexthop == d.this.nexthop

  127 

  128 There are two kinds of eroutes: shunt eroutes and ones for an IPSEC SA

  129 Group.  Most eroutes are associated with and are represeented in a

  130 connection.  The exception is that some HOLD and PASS shunts do not

  131 correspond to connections; those are represented in the bare_shunt

  132 table.

  133 

  134 An eroute for an IPSEC SA Group is associated with the state object

  135 for that Group.  The existence of such an eroute is also represented

  136 by the "so_serial_t eroute_owner" field in the struct connection.  The

  137 value is the serial number of the state object for the Group.  The

  138 special value SOS_NOBODY means that there is no owner associated with

  139 this connection for the eroute and hence no normal eroute.  At most

  140 one eroute owner may exist for a particular (source subnet,

  141 destination subnet) pair.  A Pluto-managed eroute cannot be associated

  142 with an RT_UNROUTED connection.

  143 

  144 invariant: for all struct connection c:

  145     c.routing == RT_EROUTED_TUNNEL || c.eroute_owner == SOS_NOBODY

  146 

  147 invariant: for all struct connections c, d:

  148     c.this.client == d.this.client && c.that.client == d.that.client

  149         && &c != &d

  150     => c.routing == RT_UNROUTED || d.routing == RT_UNROUTED

  151 

  152 If no normal eroute is set for a particular (source subnet,

  153 destination subnet) pair for which a connection is routed, then a

  154 shunt eroute would have been installed.  This specifies what should

  155 happen to packets snared by the route.

  156 

  157 When Pluto is notified by KLIPS of a packet that has been TRAPped,

  158 there is no connection with which to associate the HOLD.  It is

  159 temporarily held in the "bare_shunt table".  If Opportunism is

  160 attempted but DNS doesn't provide Security Gateway information, Pluto

  161 will replace the HOLD with a PASS shunt.  Since this PASS isn't

  162 associated with a connection, it too will reside in the bare_shunt

  163 table.  If the HOLD can be associated with a connection, it will be

  164 removed from the bare_shunt table and represented in the connection.

  165 

  166 There are two contexts for which shunt eroutes are installed by Pluto

  167 for a particular connection.  The first context is with the prospect

  168 of dealing with packets before any negotiation has been attempted.  I

  169 call this context "prospective".  Currently is a TRAP shunt, used to

  170 catch packets for initiate opportunistic negotiation.  In the future,

  171 it might also be used to implement preordained PASS, DROP, or REJECT

  172 rules.

  173 

  174 The second context is after a failed negotiation.  I call this context

  175 "failure".  At this point a different kind of shunt eroute is

  176 appropriate.  Depending on policy, it could be PASS, DROP, or REJECT,

  177 but it is unlikely to be TRAP.  The shunt eroute should have a

  178 lifetime (this isn't yet implemented).  When the lifetime expires, the

  179 failure shunt eroute should be replaced by the prospective shunt

  180 eroute.

  181 

  182 The kind and duration of a failure shunt eroute should perhaps depend

  183 on the nature of the failure, at least as imperfectly detected by

  184 Pluto.  We haven't looked at this.  In particular, the mapping from

  185 observations to robust respose isn't obvious.

  186 

  187 The shunt eroute policies should be a function of the potential

  188 connection.  The failure shunt eroute can be specified for a

  189 particular connection with the flags --pass and --drop in a connection

  190 definition.  There are four combinations, and each has a distinct

  191 meaning.  The failure shunt eroute is incompletely implemented and

  192 cannot be represented in /etc/ipsec.conf.

  193 

  194 There is as yet no control over the prospective shunt eroute: it is

  195 always TRAP as far as Pluto is concerned.  This is probably

  196 reasonable: any other fate suggests that no negotiation will be done,

  197 and so a connection definition is inappropriate.  These should be

  198 implemented as manual conns.  There remains the issue of whether Pluto

  199 should be aware of them -- currently it is not.

  200 

  201 

  202 Routines:

  203 

  204 [in kernel.c]

  205 

  206 bool do_command(struct connection *c, const char *verb)

  207     Run the updown script to perform such tasks as installing a route

  208     and adjust the firewall.

  209 

  210 bool could_route(struct connection *c)

  211     Check to see whether we could route and eroute the connection.

  212     <- shunt_eroute_connection (to check if --route can be performed)

  213     <- install_inbound_ipsec_sa (to see if it will be possible

  214        to (later) install route and eroute the corresponding outbound SA)

  215     <- install_ipsec_sa (to see if the outbound SA can be routed and erouted)

  216 

  217 bool trap_connection(struct connection *c)

  218     Install a TRAP shunt eroute for this connection.  This implements

  219     "whack --route", the way an admin can specify that packets for a

  220     connection should be caught without first bringing it up.

  221 

  222 void unroute_connection(struct connection *c)

  223     Delete any eroute for a connection and unroute it if route isn't shared.

  224     <- release_connection

  225     <- whack_handle (for "whack --unroute)

  226 

  227 bool eroute_connection(struct connection *c

  228 , ipsec_spi_t spi, unsigned int proto, unsigned int satype

  229 , unsigned int op, const char *opname UNUSED)

  230     Issue PF_KEY commands to KLIPS to add, replace, or delete an eroute.

  231     The verb is specified by op and described (for logging) by opname.

  232     <- assign_hold

  233     <- sag_eroute

  234     <- shunt_eroute

  235 

  236 bool assign_hold(struct connection *c

  237 , const ip_address *src, const ip_address *dst)

  238     Take a HOLD from the bare_shunt table and assign it to a connection.

  239     If the HOLD is broadened (i.e. the connection's source or destination

  240     subnets contain more than one IP address), this will involve replacing

  241     the HOLD with a different one.

  242 

  243 bool sag_eroute(struct state *st, unsigned op, const char *opname)

  244     SA Group eroute manipulation.  The SA Group concerned is

  245     identified with a state object.

  246     <- route_and_eroute several times

  247 

  248 bool shunt_eroute(struct connection *c, unsigned int op, const char *opname)

  249     shunt eroute manipulation.  Shunt eroutes are associated with

  250     connections.

  251     <- unroute_connection

  252     <- route_and_eroute

  253     <- delete_ipsec_sa

  254 

  255 bool route_and_eroute(struct connection *c, struct state *st)

  256     Install a route and then a prospective shunt eroute or an SA group

  257     eroute.  The code assumes that could_route had previously

  258     given the go-ahead.  Any SA group to be erouted must already

  259     exist.

  260     <- shunt_eroute_connection

  261     <- install_ipsec_sa

  262 

  263 void scan_proc_shunts(void)

  264     Every SHUNT_SCAN_INTERVAL scan /proc/net/ipsec_eroute.

  265     Delete any PASS eroute in the bare_shunt table that hasn't been used

  266     within the last SHUNT_PATIENCE seconds.

  267     For any HOLD for which Pluto hasn't received an ACQUIRE (possibly

  268     lost due to congestion), act as if an ACQUIRE were received.

  269 

  270 [in connection.c]

  271 

  272 struct connection *route_owner(struct connection *c, struct connection **erop)

  273     Find the connection to connection c's peer's client with the

  274     largest value of .routing.  All other things being equal,

  275     preference is given to c.  Return NULL if no connection is routed

  276     at all.  If erop is non-null, sets it to a connection sharing both

  277     our client subnet and peer's client subnet with the largest value

  278     of .routing.

  279     The return value is used to find other connections sharing

  280     a route.  The value of *erop is used to find other connections

  281     sharing an eroute.

  282     <- could_route (to find any conflicting routes or eroutes)

  283     <- unroute_connection (to find out if our route is still in use

  284        after this connection is finished with it)

  285     <- install_inbound_ipsec_sa (to find other IPSEC SAs for the

  286        same peer clients; when we find them WE KILL THEM; a

  287        kludge to deal with road warriors reconnecting)

  288     <- route_and_eroute (to find all the connections from which the

  289        route or eroute is being stolen)

  290 

  291 Uses:

  292 

  293 - setting up route & shunt eroute to TRAP packets for opportunism

  294   (whack --route).  Perhaps also manually designating DROP, REJECT, or

  295   PASS for certain packets.

  296 

  297   whack_handle() responds to --route; calls route_connection()

  298 

  299 

  300 - removing same (whack --unroute)

  301 

  302   whack_handle() responds to --unroute; calls unroute_connection()

  303 

  304 - installing route & normal eroute for a newly negotiated group of

  305   outbound IPSEC SAs

  306 

  307   + perhaps an (additional) route is not needed: if the negotiation

  308     was initiated by a TRAPped outgoing packet, then there must

  309     already have been a route that got the packet to ipsecN.  Mind

  310     you, it could have been the wrong N!

  311 

  312   install_ipsec_sa()

  313 

  314 - updating a normal eroute when a new group of IPSEC SAs replaces

  315   an old one due to rekeying.

  316 

  317   install_ipsec_sa()

  318 

  319 - replacing an old eroute when a negotiation fails.  But this is

  320   tricky.  If this was a rekeying, we should just leave the old

  321   normal eroute be -- it might still work.  Otherwise, this was

  322   an initial negotiation: we should replace the shunt eroute

  323   with one appropriate for the failure context.

  324 

  325 - when a group of IPSEC SAs dies or is killed, and it had the eroute,

  326   its normal eroute should be replaced by a shunt eroute.  If there

  327   was an attempt to replace the group, the replacement is in the

  328   failure context; otherwise the replacement is in the prospective

  329   context.

本文轉自 拾瓦興閣 51CTO部落格,原文連結:http://blog.51cto.com/ponyjia/933624

繼續閱讀