.. contents:: Table of Contents :depth: 3 .. |TCP-MD5| replace:: TCP MD5 Signature Option .. |netvirt| replace:: odl-netvirt-impl feature ================================================================ Support for TCP MD5 Signature Option configuration of Quagga BGP ================================================================ https://git.opendaylight.org/gerrit/#/q/topic:qbgp-tcp-md5-signature-option This functionality adds support to |netvirt| to configure the |TCP-MD5| [RFC2385]_ password in Quagga BGPs [QBGP]_. Problem description =================== Quagga [QBGP]_ supports |TCP-MD5| [RFC2385]_ in BGP traffic but current |netvirt| implementation lacks support to configure the required passwords. Use Cases --------- UC1: Protect (Quagga [QBGP]_) BGP and DC gateway BGP interface using |TCP-MD5| [RFC2385]_. Proposed change =============== The following components need to be enhanced: * BGP Manager Pipeline changes ---------------- No pipeline changes. API changes ----------- Changes will be needed in ``ebgp.yang``, and ``qbgp.thrift``. YANG changes ^^^^^^^^^^^^ A new optional leaf with the |TCP-MD5| [RFC2385]_ password is added (by means of a choice) to list ``neighbors``. .. code-block:: none :caption: ebgp.yang additions typedef tcp-md5-signature-password-type { type string { length 1..80; } // subtype string description "The shared secret used by TCP MD5 Signature Option. The length is limited to 80 chars because A) it is identified by the RFC as current practice and B) it is the maximum length accepted by Quagga implementation."; reference "RFC 2385"; } // typedef tcp-md5-signature-password-type grouping tcp-security-option-grouping { description "TCP security options."; choice tcp-security-option { description "The tcp security option in use, if any."; case tcp-md5-signature-option { description "The connection uses TCP MD5 Signature Option."; reference "RFC 2385"; leaf tcp-md5-signature-password { type tcp-md5-signature-password-type; description "The shared secret used to sign the packets."; } // leaf tcp-md5-signature-password } // case tcp-md5-signature-option } // choice tcp-security-option } // grouping tcp-security-option-grouping .. code-block:: none :caption: ebgp.yang modifications list neighbors { key "address"; leaf address { type inet:ipv4-address; mandatory "true"; } leaf remote-as { type uint32; mandatory "true"; } + use tcp-security-option-grouping; Thrift changes ^^^^^^^^^^^^^^ A new function ``setPeerSecret`` is added to the service ``BgpConfigurator``. .. code-block:: none :caption: qbgp.thrift modifications --- a/vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/thrift/idl/qbgp.thrift +++ b/vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/thrift/idl/qbgp.thrift @@ -31,6 +31,8 @@ const i32 GET_RTS_NEXT = 1 * ERR_NOT_ITER when GET_RTS_NEXT is called without * initializing with GET_RTS_INIT * ERR_PARAM when there is an issue with params + * ERR_NOT_SUPPORTED when the server does not support + * the operation. */ const i32 BGP_ERR_FAILED = 1 @@ -38,6 +40,7 @@ const i32 BGP_ERR_ACTIVE = 10 const i32 BGP_ERR_INACTIVE = 11 const i32 BGP_ERR_NOT_ITER = 15 const i32 BGP_ERR_PARAM = 100 +const i32 BGP_ERR_NOT_SUPPORTED = 200 // these are the supported afi-safi combinations enum af_afi { @@ -122,6 +125,33 @@ service BgpConfigurator { 6:i32 stalepathTime, 7:bool announceFlush), i32 stopBgp(1:i64 asNumber), i32 createPeer(1:string ipAddress, 2:i64 asNumber), + + /* 'setPeerSecret' sets the shared secret needed to protect the peer + * connection using TCP MD5 Signature Option (see rfc 2385). + * + * Params: + * + * 'ipAddress' is the peer (neighbour) address. Mandatory. + * + * 'rfc2385_sharedSecret' is the secret. Mandatory. Length must be + * greater than zero. + * + * Return codes: + * + * 0 on success. + * + * BGP_ERR_FAILED if 'ipAddress' is missing or unknown. + * + * BGP_ERR_PARAM if 'rfc2385_sharedSecret' is missing or invalid (e.g. + * it is too short or too long). + * + * BGP_ERR_INACTIVE when there is no session. + * + * BGP_ERR_NOT_SUPPORTED when TCP MD5 Signature Option is not supported + * (e.g. the underlying TCP stack does not support it) + * + */ + i32 setPeerSecret(1:string ipAddress, 2:string rfc2385_sharedSecret), i32 deletePeer(1:string ipAddress) i32 addVrf(1:layer_type l_type, 2:string rd, 3:list irts, 4:list erts), i32 delVrf(1:string rd), An old server (i.e. using a previous version of ``qbgp.thrift``) will return a ``TApplicationException`` with type ``UNKNOWN_METHOD``. See [TBaseProcessor]_. Configuration impact -------------------- No configuration parameters deprecated. New optional leaf ``tcp-md5-signature-password`` does not impact existing deployments. The recommended AAA configuration (See `Security considerations`_) may impact existing deployments. Clustering considerations ------------------------- NA Other Infra considerations -------------------------- Signature mismatch ^^^^^^^^^^^^^^^^^^ On signature mismatch |TCP-MD5| [RFC2385]_ (page 2) specifies the following behaviour: .. code-block:: none :caption: RFC 2385 page 2 Upon receiving a signed segment, the receiver must validate it by calculating its own digest from the same data (using its own key) and comparing the two digest. A failing comparison must result in the segment being dropped and must not produce any response back to the sender. Logging the failure is probably advisable. A BGP will be unable to connect with a neighbor with a wrong password because the TCP SYN,ACK will be dropped. The neighbor state will bounce between "Active" and "Connect" while it retries. Security considerations ----------------------- ``tcp-md5-signature-password`` is stored in clear in the datastore. This is a limitation of the proposed change. Because ``tcp-md5-signature-password`` is stored in clear the REST access to ``neighbors`` list should be restricted. See the following AAA configuration examples: .. code-block:: none :caption: etc/shiro.ini example # # DISCOURAGED since Carbon # /config/ebgp:bgp/neighbors/** = authBasic, roles[admin] .. code-block:: json :caption: AAA MDSALDynamicAuthorizationFilter example { "aaa:policies": { "aaa:policies": [ { "aaa:resource": "/restconf/config/ebgp:bgp/neighbors/**", "aaa:permissions": [ { "aaa:role": "admin", "aaa:actions": [ "get","post","put","patch","delete" ] } ] } ] } } If ``BgpConfigurator`` thrift service is not secured then ``tcp-md5-signature-password`` goes clear on the wire. Quagga [QBGP]_ (up to version 1.0) keeps the password in memory in clear. The password can be retrieved through Quagga's configuration interface. Scale and Performance Impact ---------------------------- Negligible scale or performance impacts. * datastore: A bounded (<=80) string per configured neighbor. * Traffic (thrift ``BgpConfigurator`` service): A bounded (<=80) string field per neighbor addition operation. Targeted Release ---------------- Carbon Alternatives ------------ Three alternatives have been considered in order to avoid storing the plain password in datastore: RPC, post-update, and transparent encryption. They are briefly described below. The best alternative is transparent encryption, but in Carbon time-frame is not feasible. The post-update alternative does not actually solve the limitation. The RPC alternative is feasible in Carbon time-frame but, given that currently ``BgpConfigurator`` thrift service is not secured, to add an RPC does not pull its weight. RPC encryption ^^^^^^^^^^^^^^ A new RPC ``add-neighbor(address, as-number[, tcp-md5-signature-password])`` is in charge of create ``neighbors`` elements. The password is salted and encrypted with ``aaa-encryption-service``. Both the salt and the encrypted password are stored in the ``neighbors`` element. Post-update encryption ^^^^^^^^^^^^^^^^^^^^^^ The ``neighbors`` element contains both a ``plain-password`` leaf and a ``encrypted-password-with-salt`` leaf. The listener ``BgpConfigurationManager.NeighborsReactor`` is in charge of encrypt and remove the ``plain-password`` leaf when it is present (and the encrypted one is not). This alternative does not really solve the limitation because during a brief period the password is stored in plain. Transparent encryption ^^^^^^^^^^^^^^^^^^^^^^ A plain value is provided in REST write operations but it is `automagically` encrypted before it reaches MD-SAL. Read operations never decrypts the encrypted values. This alternative impacts at least ``aaa``, ``yangtools``, and ``netconf`` projects. It can not possibly be done in Carbon. Usage ===== Features to Install ------------------- odl-netvirt-openstack REST API -------- The RESTful API for neighbors creation (``/restconf/config/ebgp:bgp/neighbors/{address}``) will be enhanced to accept an additional ``tcp-md5-signature-password`` attribute: .. code-block:: json { "neighbors": { "address": "192.168.50.2", "remote-as": "2791", "tcp-md5-signature-password": "password" }} CLI --- A new option ``--tcp-md5-password`` will be added to commands ``odl:configure-bgp`` and ``odl:bgp-nbr``. .. code-block:: none opendaylight-user@root> odl:configure-bgp -op add-neighbor --ip 192.168.50.2 --as-num 2791 --tcp-md5-password password opendaylight-user@root> odl:bgp-nbr --ip-address 192.168.50.2 --as-number 2791 --tcp-md5-password password add Implementation ============== Assignee(s) ----------- Primary assignee: Jose-Santos Pulido, JoseSantos, jose.santos.pulido.garcia@ericsson.com Other contributors: TBD Work Items ---------- * https://trello.com/c/87MAFjRf #. Spec #. ``ebgp.yang`` #. ``BgpConfigurator`` thrift service (both idl and client) #. ``BgpConfigurationManager.NeighborsReactor`` #. ``ConfigureBgpCli`` Dependencies ============ Internal -------- No internal dependencies are added or removed. External -------- To enable |TCP-MD5| [RFC2385]_ in a BGP the following conditions need to be met: * ``BgpConfigurator`` thrift service provider (e.g. ``Zebra Remote Procedure Call`` [ZRPC]_) must support the new function ``setPeerSecret``. * BGP's TCP stack must support |TCP-MD5| (e.g. in linux the kernel option CONFIG_TCP_MD5SIG must be set). Testing ======= Unit Tests ---------- Currently ``bgpmanager`` has no unit tests related to configuration. Integration Tests ----------------- Currently ``bgpmanager`` has no integration tests. CSIT ---- Currently there is no CSIT test exercising ``bgpmanager``. Documentation Impact ==================== Currently there is no documentation related to ``bgpmanager``. References ========== .. [QBGP] `Quagga Routing Suite `__ .. [RFC2385] `IETF RFC 2385: Protection of BGP Sessions via the TCP MD5 Signature Option `__ .. [TBaseProcessor] `thrift java library's TBaseProcessor.process `__ .. [ZRPC] `Zebra Remote Procedure Call `__ .. vi: ts=3 sts=3 sw=3 expandtab ai tw=77 :