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


点赞