strongswan ipsec 向内核下发SA和Policy部分

目录

kernel_netlink插件

插件初始化

add_sa和add_policy


kernel_netlink插件

strongswan ipsec 向内核下发SA和Policy部分可以是kernel_netlink插件的方式实现的。

其他的插件有:

Plugin NameDescription
kernel-libipsecIPsec "kernel" interface in user-space using libipsec
kernel-netlinkIPsec/Networking kernel interface using Linux Netlink
kernel-pfkeyIPsec kernel interface using PF_KEY
kernel-wfpIPsec backend for the Windows platform, using the Windows Filtering Platform

libstrongswan/plugins/plugin_loader.c里面会将指定路径下的库文件当做strongswan的插件来加载,所以strongswan会把kernel_netlink编译成库文件,libcharon/Makefile文件中关键内容如下:

Makefile

am__append_108 = plugins/kernel_netlink
#am__append_109 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la

/* file: libcharon/Makefile */

 Makeifle.am

if USE_KERNEL_NETLINK
  SUBDIRS += plugins/kernel_netlink
if MONOLITHIC
  libcharon_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la
endif
endif

 根据上述Makefile编译生成的libstrongswan-kernel-netlink.so文件如下:

strongswan$ grep kernel_netlink_plugin_create . -r
Binary file ./src/libcharon/plugins/kernel_netlink/.libs/libstrongswan-kernel-netlink.so matches
Binary file ./src/libcharon/plugins/kernel_netlink/.libs/kernel_netlink_plugin.o matches
./src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c:plugin_t *kernel_netlink_plugin_create()

 libstrongswan/plugins/plugin_loader.c文件中 _load_plugins函数会遍历路径下的库文件来加载kenel-netlink插件。

METHOD(plugin_loader_t, load_plugins, bool, private_plugin_loader_t *this, char *list);

plugin_loader_t *plugin_loader_create()
{
        private_plugin_loader_t *this;

        INIT(this,
                .public = {
                        .add_static_features = _add_static_features,
                        .load = _load_plugins,
                        .add_path = _add_path,
                        .reload = _reload,
                        .unload = _unload,
                        .create_plugin_enumerator = _create_plugin_enumerator,
                        .has_feature = _has_feature,
                        .loaded_plugins = _loaded_plugins,
                        .status = _status,
                        .destroy = _destroy,
                },
                .plugins = linked_list_create(),
                .loaded = linked_list_create(),
                .features = hashlist_create(
                                                        (hashtable_hash_t)registered_feature_hash,
                                                        (hashtable_equals_t)registered_feature_equals, 64),
                .get_features = dlsym(RTLD_DEFAULT, "plugin_loader_feature_filter"),
        );

        if (!this->get_features)
        {
                this->get_features = get_features_default;
        }

        return &this->public;
}

/* file: libstrongswan/plugins/plugin_loader.c */

插件初始化

插件注册函数为kernel_ipsec_register();

# grep kernel_ipsec_register . -r
./plugins/kernel_wfp/kernel_wfp_plugin.c:               PLUGIN_CALLBACK(kernel_ipsec_register, kernel_wfp_ipsec_create),
./plugins/load_tester/load_tester_plugin.c:             PLUGIN_CALLBACK(kernel_ipsec_register, load_tester_ipsec_create),
./plugins/kernel_pfkey/kernel_pfkey_plugin.c:           PLUGIN_CALLBACK(kernel_ipsec_register, kernel_pfkey_ipsec_create),
./plugins/kernel_netlink/kernel_netlink_plugin.c:               PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
./plugins/kernel_libipsec/kernel_libipsec_plugin.c:             PLUGIN_CALLBACK(kernel_ipsec_register, kernel_libipsec_ipsec_create),
./kernel/kernel_ipsec.c:bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
./kernel/kernel_ipsec.h:bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,

 kernel_netlink插件中关键函数为kernel_netlink_plugin_create();

METHOD(plugin_t, get_features, int,
        private_kernel_netlink_plugin_t *this, plugin_feature_t *features[])
{
        static plugin_feature_t f[] = {
                PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
                        PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
                PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create),
                        PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
        };
        *features = f;
        return countof(f);
}

plugin_t *kernel_netlink_plugin_create()
{
        private_kernel_netlink_plugin_t *this;

        ......

        INIT(this,
                .public = {
                        .plugin = {
                                .get_name = _get_name,
                                .get_features = _get_features,
                                .reload = _reload,
                                .destroy = _destroy,
                        },
                },
        );

        reload(this);

        return &this->public.plugin;
}

/* file: libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c */

 kernel_netlink_ipsec_create会对SA和Policy的管理接口初始化并初始化xfrm的用户态socket。

kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
{
        private_kernel_netlink_ipsec_t *this;
        bool register_for_events = TRUE;

        INIT(this,
                .public = {
                        .interface = {
                                .get_features = _get_features,
                                .get_spi = _get_spi,
                                .get_cpi = _get_cpi,
                                .add_sa  = _add_sa,
                                .update_sa = _update_sa,
                                .query_sa = _query_sa,
                                .del_sa = _del_sa,
                                .flush_sas = _flush_sas,
                                .add_policy = _add_policy,
                                .query_policy = _query_policy,
                                .del_policy = _del_policy,
                                .flush_policies = _flush_policies,
                                .bypass_socket = _bypass_socket,
                                .enable_udp_decap = _enable_udp_decap,
                                .destroy = _destroy,
                        },
                },
                .policies = hashtable_create((hashtable_hash_t)policy_hash,
                                                                         (hashtable_equals_t)policy_equals, 32),
                .sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
                                                                (hashtable_equals_t)ipsec_sa_equals, 32),
                .bypass = array_create(sizeof(bypass_t), 0),
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
                .get_priority = dlsym(RTLD_DEFAULT,
                                                          "kernel_netlink_get_priority_custom"),
                .policy_update = lib->settings->get_bool(lib->settings,
                                        "%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
                .install_routes = lib->settings->get_bool(lib->settings,
                                                        "%s.install_routes", TRUE, lib->ns),
                .proto_port_transport = lib->settings->get_bool(lib->settings,
                                                "%s.plugins.kernel-netlink.set_proto_port_transport_sa",
                                                FALSE, lib->ns),
        );

        if (streq(lib->ns, "starter"))
        {       /* starter has no threads, so we do not register for kernel events */
                register_for_events = FALSE;
        }

        this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names,
                                lib->settings->get_bool(lib->settings,
                                        "%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns));
        if (!this->socket_xfrm)
        {
                destroy(this);
                return NULL;
        }

        setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
        setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);

        if (register_for_events)
        {
                struct sockaddr_nl addr;

                memset(&addr, 0, sizeof(addr));
                addr.nl_family = AF_NETLINK;

                /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
                this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
                if (this->socket_xfrm_events <= 0)
                {
                        DBG1(DBG_KNL, "unable to create XFRM event socket: %s (%d)",
                                 strerror(errno), errno);
                        destroy(this);
                        return NULL;
                }
                addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
                                                 XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
                if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
                {
                        DBG1(DBG_KNL, "unable to bind XFRM event socket: %s (%d)",
                                 strerror(errno), errno);
                        destroy(this);
                        return NULL;
                }
                lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
                                                  (watcher_cb_t)receive_events, this);
        }

        netlink_find_offload_feature(lib->settings->get_str(lib->settings,
                                        "%s.plugins.kernel-netlink.hw_offload_feature_interface",
                                        "lo", lib->ns));

        return &this->public;
}

/* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

add_sa和add_policy

_add_sa();的实现函数为,根据SA数据,组装成NetLink消息体下发给内核

METHOD(kernel_ipsec_t, add_sa, status_t,
        private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
        kernel_ipsec_add_sa_t *data)
{
        netlink_buf_t request;
        const char *alg_name;
        char markstr[32] = "";
        struct nlmsghdr *hdr;
        struct xfrm_usersa_info *sa;
        uint16_t icv_size = 64, ipcomp = data->ipcomp;
        ipsec_mode_t mode = data->mode, original_mode = data->mode;
        traffic_selector_t *first_src_ts, *first_dst_ts;
        status_t status = FAILED;

        .......

        memset(&request, 0, sizeof(request));
        format_mark(markstr, sizeof(markstr), id->mark);

        ......

        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        hdr->nlmsg_type = data->update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));

        sa = NLMSG_DATA(hdr);
        host2xfrm(id->src, &sa->saddr);
        host2xfrm(id->dst, &sa->id.daddr);
        sa->id.spi = id->spi;
        sa->id.proto = id->proto;
        sa->family = id->src->get_family(id->src);
        sa->mode = mode2kernel(mode);

        if (!data->copy_df)
        {
                sa->flags |= XFRM_STATE_NOPMTUDISC;
        }

        if (!data->copy_ecn)
        {
                sa->flags |= XFRM_STATE_NOECN;
        }

        if (data->inbound)
        {
                switch (data->copy_dscp)
                {
                        case DSCP_COPY_YES:
                        case DSCP_COPY_IN_ONLY:
                                sa->flags |= XFRM_STATE_DECAP_DSCP;
                                break;
                        default:
                                break;
                }
        }
        else
        {
                switch (data->copy_dscp)
                {
                        case DSCP_COPY_IN_ONLY:
                        case DSCP_COPY_NO:
                        {
                                /* currently the only extra flag */
                                if (!add_uint32(hdr, sizeof(request), XFRMA_SA_EXTRA_FLAGS,
                                                                XFRM_SA_XFLAG_DONT_ENCAP_DSCP))
                                {
                                        goto failed;
                                }
                                break;
                        }
                        default:
                                break;
                }
        }

        switch (mode)
        {
                case MODE_TUNNEL:
                        sa->flags |= XFRM_STATE_AF_UNSPEC;
                        break;
                case MODE_BEET:
                case MODE_TRANSPORT:
                        if (original_mode == MODE_TUNNEL)
                        {       /* don't install selectors for switched SAs.  because only one
                                 * selector can be installed other traffic would get dropped */
                                break;
                        }
                        if (data->src_ts->get_first(data->src_ts,
                                                                                (void**)&first_src_ts) == SUCCESS &&
                                data->dst_ts->get_first(data->dst_ts,
                                                                                (void**)&first_dst_ts) == SUCCESS)
                        {
                                sa->sel = ts2selector(first_src_ts, first_dst_ts,
                                                                          data->interface);
                                if (!this->proto_port_transport)
                                {
                                        /* don't install proto/port on SA. This would break
                                         * potential secondary SAs for the same address using a
                                         * different prot/port. */
                                        sa->sel.proto = 0;
                                        sa->sel.dport = sa->sel.dport_mask = 0;
                                        sa->sel.sport = sa->sel.sport_mask = 0;
                                }
                        }
                        break;
                default:
                        break;
        }
        if (id->proto == IPPROTO_AH && sa->family == AF_INET)
        {       /* use alignment to 4 bytes for IPv4 instead of the incorrect 8 byte
                 * alignment that's used by default but is only valid for IPv6 */
                sa->flags |= XFRM_STATE_ALIGN4;
        }

        sa->reqid = data->reqid;
        sa->lft.soft_byte_limit = XFRM_LIMIT(data->lifetime->bytes.rekey);
        sa->lft.hard_byte_limit = XFRM_LIMIT(data->lifetime->bytes.life);
        sa->lft.soft_packet_limit = XFRM_LIMIT(data->lifetime->packets.rekey);
        sa->lft.hard_packet_limit = XFRM_LIMIT(data->lifetime->packets.life);
        /* we use lifetimes since added, not since used */
        sa->lft.soft_add_expires_seconds = data->lifetime->time.rekey;
        sa->lft.hard_add_expires_seconds = data->lifetime->time.life;
        sa->lft.soft_use_expires_seconds = 0;
        sa->lft.hard_use_expires_seconds = 0;

        switch (data->enc_alg)
        {
                case ENCR_UNDEFINED:
                        /* no encryption */
                        break;
                case ENCR_AES_CCM_ICV16:
                case ENCR_AES_GCM_ICV16:
                case ENCR_NULL_AUTH_AES_GMAC:
                case ENCR_CAMELLIA_CCM_ICV16:
                case ENCR_CHACHA20_POLY1305:
                        icv_size += 32;
                        /* FALL */
                case ENCR_AES_CCM_ICV12:
                case ENCR_AES_GCM_ICV12:
                case ENCR_CAMELLIA_CCM_ICV12:
                        icv_size += 32;
                        /* FALL */
                case ENCR_AES_CCM_ICV8:
                case ENCR_AES_GCM_ICV8:
                case ENCR_CAMELLIA_CCM_ICV8:
                {
                        struct xfrm_algo_aead *algo;

                        alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
                        if (alg_name == NULL)
                        {
                                DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
                                                 encryption_algorithm_names, data->enc_alg);
                                        goto failed;
                        }
                        DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
                                 encryption_algorithm_names, data->enc_alg,
                                 data->enc_key.len * 8);

                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
                                                                   sizeof(*algo) + data->enc_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
                        algo->alg_key_len = data->enc_key.len * 8;
                        algo->alg_icv_len = icv_size;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
                        memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
                        break;
                }
                default:
                {
                        struct xfrm_algo *algo;

                        alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
                        if (alg_name == NULL)
                        {
                                DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
                                         encryption_algorithm_names, data->enc_alg);
                                goto failed;
                        }
                        DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
                                 encryption_algorithm_names, data->enc_alg,
                                 data->enc_key.len * 8);

                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
                                                                   sizeof(*algo) + data->enc_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
                        algo->alg_key_len = data->enc_key.len * 8;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
                        memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
                }
        }
        if (data->int_alg != AUTH_UNDEFINED)
        {
                u_int trunc_len = 0;

                alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
                if (alg_name == NULL)
                {
                        DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
                                 integrity_algorithm_names, data->int_alg);
                        goto failed;
                }
                DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
                         integrity_algorithm_names, data->int_alg, data->int_key.len * 8);

                switch (data->int_alg)
                {
                        case AUTH_HMAC_MD5_128:
                        case AUTH_HMAC_SHA2_256_128:
                                trunc_len = 128;
                                break;
                        case AUTH_HMAC_SHA1_160:
                                trunc_len = 160;
                                break;
                        case AUTH_HMAC_SHA2_256_256:
                                trunc_len = 256;
                                break;
                        case AUTH_HMAC_SHA2_384_384:
                                trunc_len = 384;
                                break;
                        case AUTH_HMAC_SHA2_512_512:
                                trunc_len = 512;
                                break;
                        default:
                                break;
                }

        ......

        if (data->encap)
        {
                struct xfrm_encap_tmpl *tmpl;

                tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
                if (!tmpl)
                {
                        goto failed;
                }
                tmpl->encap_type = UDP_ENCAP_ESPINUDP;
                tmpl->encap_sport = htons(id->src->get_port(id->src));
                tmpl->encap_dport = htons(id->dst->get_port(id->dst));
                memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
                /* encap_oa could probably be derived from the
                 * traffic selectors [rfc4306, p39]. In the netlink kernel
                 * implementation pluto does the same as we do here but it uses
                 * encap_oa in the pfkey implementation.
                 * BUT as /usr/src/linux/net/key/af_key.c indicates the kernel ignores
                 * it anyway
                 *   -> does that mean that NAT-T encap doesn't work in transport mode?
                 * No. The reason the kernel ignores NAT-OA is that it recomputes
                 * (or, rather, just ignores) the checksum. If packets pass the IPsec
                 * checks it marks them "checksum ok" so OA isn't needed. */
        }



        if (id->if_id && !add_uint32(hdr, sizeof(request), XFRMA_IF_ID, id->if_id))
        {
                goto failed;
        }


        if (data->tfc && id->proto == IPPROTO_ESP && mode == MODE_TUNNEL)
        {       /* the kernel supports TFC padding only for tunnel mode ESP SAs */
                if (!add_uint32(hdr, sizeof(request), XFRMA_TFCPAD, data->tfc))
                {
                        goto failed;
                }
        }

        ......

        status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
        if (status == NOT_FOUND && data->update)
        {
                DBG1(DBG_KNL, "allocated SPI not found anymore, try to add SAD entry");
                hdr->nlmsg_type = XFRM_MSG_NEWSA;
                status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
        }

        ......

        status = SUCCESS;

failed:
        memwipe(&request, sizeof(request));
        return status;
}

/* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

_add_policy的实现函数为,函数中会调用add_policy_internal();最终通过NeiLink message来向内核下发policy。

METHOD(kernel_ipsec_t, add_policy, status_t,
        private_kernel_netlink_ipsec_t *this, kernel_ipsec_policy_id_t *id,
        kernel_ipsec_manage_policy_t *data)
{
        policy_entry_t *policy, *current;
        policy_sa_t *assigned_sa, *current_sa;
        enumerator_t *enumerator;
        bool found = FALSE, update = TRUE;
        char markstr[32] = "";
        uint32_t cur_priority = 0;
        int use_count;

        /* create a policy */
        INIT(policy,
                .sel = ts2selector(id->src_ts, id->dst_ts, id->interface),
                .mark = id->mark.value & id->mark.mask,
                .if_id = id->if_id,
                .direction = id->dir,
                .reqid = data->sa->reqid,
        );
        format_mark(markstr, sizeof(markstr), id->mark);

        /* find the policy, which matches EXACTLY */
        this->mutex->lock(this->mutex);
        current = this->policies->get(this->policies, policy);
        if (current)
        {
                if (current->reqid && data->sa->reqid &&
                        current->reqid != data->sa->reqid)
                {
                        DBG1(DBG_CFG, "unable to install policy %R === %R %N%s for reqid "
                                 "%u, the same policy for reqid %u exists",
                                 id->src_ts, id->dst_ts, policy_dir_names, id->dir, markstr,
                                 data->sa->reqid, current->reqid);
                        policy_entry_destroy(this, policy);
                        this->mutex->unlock(this->mutex);
                        return INVALID_STATE;
                }
                /* use existing policy */
                DBG2(DBG_KNL, "policy %R === %R %N%s already exists, increasing "
                         "refcount", id->src_ts, id->dst_ts, policy_dir_names, id->dir,
                         markstr);
                policy_entry_destroy(this, policy);
                policy = current;
                found = TRUE;

                policy->waiting++;
                while (policy->working)
                {
                        this->condvar->wait(this->condvar, this->mutex);
                }
                policy->waiting--;
                policy->working = TRUE;
        }
        else
        {       /* use the new one, if we have no such policy */
                policy->used_by = linked_list_create();
                this->policies->put(this->policies, policy, policy);
        }

        /* cache the assigned IPsec SA */
        assigned_sa = policy_sa_create(this, id->dir, data->type, data->src,
                                                                   data->dst, id->src_ts, id->dst_ts, id->mark,
                                                                   id->if_id, data->sa);
        assigned_sa->auto_priority = get_priority(policy, data->prio, id->interface);
        assigned_sa->priority = this->get_priority ? this->get_priority(id, data)
                                                                                           : data->manual_prio;
        assigned_sa->priority = assigned_sa->priority ?: assigned_sa->auto_priority;

        /* insert the SA according to its priority */
        enumerator = policy->used_by->create_enumerator(policy->used_by);
        while (enumerator->enumerate(enumerator, (void**)&current_sa))
        {
                if (current_sa->priority > assigned_sa->priority)
                {
                        break;
                }
                if (current_sa->priority == assigned_sa->priority)
                {
                        /* in case of equal manual prios order SAs by automatic priority */
                        if (current_sa->auto_priority > assigned_sa->auto_priority)
                        {
                                break;
                        }
                        /* prefer SAs with a reqid over those without */
                        if (current_sa->auto_priority == assigned_sa->auto_priority &&
                                (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid))
                        {
                                break;
                        }
                }
                if (update)
                {
                        cur_priority = current_sa->priority;
                        update = FALSE;
                }
        }
        policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa);
        enumerator->destroy(enumerator);

        use_count = policy->used_by->get_count(policy->used_by);
        if (!update)
        {       /* we don't update the policy if the priority is lower than that of
                 * the currently installed one */
                policy_change_done(this, policy);
                DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u, "
                         "refcount %d]", id->src_ts, id->dst_ts, policy_dir_names,
                         id->dir, markstr, cur_priority, use_count);
                return SUCCESS;
        }
        policy->reqid = assigned_sa->sa->cfg.reqid;

        if (this->policy_update)
        {
                found = TRUE;
        }

        DBG2(DBG_KNL, "%s policy %R === %R %N%s [priority %u, refcount %d]",
                 found ? "updating" : "adding", id->src_ts, id->dst_ts,
                 policy_dir_names, id->dir, markstr, assigned_sa->priority, use_count);

        if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to %s policy %R === %R %N%s",
                         found ? "update" : "add", id->src_ts, id->dst_ts,
                         policy_dir_names, id->dir, markstr);
                return FAILED;
        }
        return SUCCESS;
}

/* file: libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c */

参考资料:

[ipsec][strongswan] strongswan源码分析--(一)SA整体分析 - toong - 博客园 (cnblogs.com)icon-default.png?t=M276https://www.cnblogs.com/hugetong/p/11143366.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
强烈推荐使用 strongSwan 来搭建 IPsec 环境。以下是基本的步骤: 1. 安装 strongSwan 对于 Ubuntu/Debian 用户: ``` sudo apt-get update sudo apt-get install strongswan ``` 对于 CentOS/RHEL 用户: ``` sudo yum install epel-release sudo yum install strongswan ``` 2. 配置 strongSwan strongSwan 的主配置文件位于 /etc/ipsec.conf。在此文件中,您需要指定以下内容: - IPsec 隧道的本地和远程端点。 - 加密和认证算法。 - 交换密钥的方式(例如使用预共享密钥或使用证书)。 以下是一个示例配置文件: ``` # /etc/ipsec.conf - strongSwan IPsec configuration file config setup charondebug="all" uniqueids=yes conn myvpn left=%defaultroute leftid=@vpn-server leftsubnet=192.168.1.0/24 right=%any rightid=@vpn-client rightsubnet=10.0.0.0/24 ike=aes256-sha256-modp2048! esp=aes256-sha256-modp2048! authby=secret auto=start ``` 在上面的示例中,我们定义了一个名为“myvpn”的连接,并指定了本地和远程端点的 IP 地址和子网。我们还指定了 IKE 和 ESP 的加密和认证算法,以及使用预共享密钥进行身份验证。 3. 配置 IPsec 预共享密钥 在上面的配置文件中,我们使用了预共享密钥进行身份验证。因此,我们需要在 /etc/ipsec.secrets 文件中定义这些密钥。以下是一个示例文件: ``` # /etc/ipsec.secrets - strongSwan IPsec secrets file @vpn-server @vpn-client : PSK "mysecret" ``` 在上面的示例中,我们定义了一个名为“mysecret”的预共享密钥,它将用于身份验证。 4. 启动 strongSwan 启动 strongSwan 服务: ``` sudo systemctl start strongswan ``` 5. 验证 IPsec 连接 使用以下命令检查 strongSwan 是否已成功建立连接: ``` sudo ipsec status ``` 如果一切正常,您应该看到类似以下输出: ``` Security Associations (1 up, 0 connecting): myvpn[1]: ESTABLISHED 2 minutes ago, 192.168.1.1[vpn-server]...10.0.0.1[vpn-client] myvpn[1]: IKEv2 SPIs: 5e7e0f1e6b4d6b37_i* 3c8f23a81b1425d0_r, pre-shared key reauthentication in 54 minutes myvpn[1]: IKE proposal: AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048 myvpn{1}: INSTALLED, TUNNEL, ESP in UDP SPIs: c7e4a8a2_i 13a3b0f1_o myvpn{1}: AES_CBC_256/HMAC_SHA2_256_128, 0 bytes_i, 0 bytes_o, rekeying in 32 minutes ``` 恭喜您,您已成功搭建了一个 strongSwan IPsec 环境!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值