Merge branch 'libipsec-raw-esp'
This adds support for sending/receiving ESP packets without UDP encapsulation to libipsec and kernel-libipsec. Only Linux is currently supported and the feature is disabled by default.
This commit is contained in:
@@ -5,3 +5,10 @@ charon.plugins.kernel-libipsec.allow_peer_ts = no
|
|||||||
installed for such traffic (via TUN device) usually prevents further IKE
|
installed for such traffic (via TUN device) usually prevents further IKE
|
||||||
traffic. The fwmark options for the _kernel-netlink_ and _socket-default_
|
traffic. The fwmark options for the _kernel-netlink_ and _socket-default_
|
||||||
plugins can be used to circumvent that problem.
|
plugins can be used to circumvent that problem.
|
||||||
|
|
||||||
|
charon.plugins.kernel-libipsec.fwmark = charon.plugins.socket-default.fwmark
|
||||||
|
Firewall mark to set on outbound raw ESP packets.
|
||||||
|
|
||||||
|
charon.plugins.kernel-libipsec.raw_esp = no
|
||||||
|
Whether to send and receive ESP packets without UDP encapsulation if
|
||||||
|
supported on this platform and no NAT is detected.
|
||||||
|
|||||||
@@ -85,19 +85,14 @@ struct private_android_service_t {
|
|||||||
bool use_dns_proxy;
|
bool use_dns_proxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
CALLBACK(send_esp, void,
|
||||||
* Outbound callback
|
void *data, esp_packet_t *packet, bool encap)
|
||||||
*/
|
|
||||||
static void send_esp(void *data, esp_packet_t *packet)
|
|
||||||
{
|
{
|
||||||
charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
|
charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(deliver_plain, void,
|
||||||
* Inbound callback
|
private_android_service_t *this, ip_packet_t *packet)
|
||||||
*/
|
|
||||||
static void deliver_plain(private_android_service_t *this,
|
|
||||||
ip_packet_t *packet)
|
|
||||||
{
|
{
|
||||||
chunk_t encoding;
|
chunk_t encoding;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
@@ -122,10 +117,8 @@ static void deliver_plain(private_android_service_t *this,
|
|||||||
packet->destroy(packet);
|
packet->destroy(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(receiver_esp_cb, void,
|
||||||
* Receiver callback
|
void *data, packet_t *packet)
|
||||||
*/
|
|
||||||
static void receiver_esp_cb(void *data, packet_t *packet)
|
|
||||||
{
|
{
|
||||||
esp_packet_t *esp_packet;
|
esp_packet_t *esp_packet;
|
||||||
|
|
||||||
@@ -359,14 +352,10 @@ static bool setup_tun_device(private_android_service_t *this,
|
|||||||
|
|
||||||
if (!already_registered)
|
if (!already_registered)
|
||||||
{
|
{
|
||||||
charon->receiver->add_esp_cb(charon->receiver,
|
charon->receiver->add_esp_cb(charon->receiver, receiver_esp_cb, NULL);
|
||||||
(receiver_esp_cb_t)receiver_esp_cb, NULL);
|
ipsec->processor->register_inbound(ipsec->processor, deliver_plain, this);
|
||||||
ipsec->processor->register_inbound(ipsec->processor,
|
ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL);
|
||||||
(ipsec_inbound_cb_t)deliver_plain, this);
|
this->dns_proxy->register_cb(this->dns_proxy, deliver_plain, this);
|
||||||
ipsec->processor->register_outbound(ipsec->processor,
|
|
||||||
(ipsec_outbound_cb_t)send_esp, NULL);
|
|
||||||
this->dns_proxy->register_cb(this->dns_proxy,
|
|
||||||
(dns_proxy_response_cb_t)deliver_plain, this);
|
|
||||||
|
|
||||||
lib->processor->queue_job(lib->processor,
|
lib->processor->queue_job(lib->processor,
|
||||||
(job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
|
(job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
|
||||||
@@ -422,14 +411,10 @@ static void close_tun_device(private_android_service_t *this)
|
|||||||
this->tunfd = -1;
|
this->tunfd = -1;
|
||||||
this->lock->unlock(this->lock);
|
this->lock->unlock(this->lock);
|
||||||
|
|
||||||
this->dns_proxy->unregister_cb(this->dns_proxy,
|
this->dns_proxy->unregister_cb(this->dns_proxy, deliver_plain);
|
||||||
(dns_proxy_response_cb_t)deliver_plain);
|
ipsec->processor->unregister_outbound(ipsec->processor, send_esp);
|
||||||
ipsec->processor->unregister_outbound(ipsec->processor,
|
ipsec->processor->unregister_inbound(ipsec->processor, deliver_plain);
|
||||||
(ipsec_outbound_cb_t)send_esp);
|
charon->receiver->del_esp_cb(charon->receiver, receiver_esp_cb);
|
||||||
ipsec->processor->unregister_inbound(ipsec->processor,
|
|
||||||
(ipsec_inbound_cb_t)deliver_plain);
|
|
||||||
charon->receiver->del_esp_cb(charon->receiver,
|
|
||||||
(receiver_esp_cb_t)receiver_esp_cb);
|
|
||||||
close(tunfd);
|
close(tunfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||||
kernel_ipsec_add_sa_t *data)
|
kernel_ipsec_add_sa_t *data)
|
||||||
{
|
{
|
||||||
|
if (!data->encap)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ESP, "failed to add SAD entry: only UDP encapsulation is "
|
||||||
|
"supported");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||||
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
||||||
@@ -82,6 +88,12 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||||
kernel_ipsec_update_sa_t *data)
|
kernel_ipsec_update_sa_t *data)
|
||||||
{
|
{
|
||||||
|
if (!data->new_encap)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ESP, "failed to update SAD entry: can't deactivate UDP "
|
||||||
|
"encapsulation");
|
||||||
|
return NOT_SUPPORTED;
|
||||||
|
}
|
||||||
return ipsec->sas->update_sa(ipsec->sas, id->spi, id->proto, data->cpi,
|
return ipsec->sas->update_sa(ipsec->sas, id->spi, id->proto, data->cpi,
|
||||||
id->src, id->dst, data->new_src, data->new_dst, data->encap,
|
id->src, id->dst, data->new_src, data->new_dst, data->encap,
|
||||||
data->new_encap, id->mark);
|
data->new_encap, id->mark);
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ endif
|
|||||||
libstrongswan_kernel_libipsec_la_SOURCES = \
|
libstrongswan_kernel_libipsec_la_SOURCES = \
|
||||||
kernel_libipsec_plugin.h kernel_libipsec_plugin.c \
|
kernel_libipsec_plugin.h kernel_libipsec_plugin.c \
|
||||||
kernel_libipsec_ipsec.h kernel_libipsec_ipsec.c \
|
kernel_libipsec_ipsec.h kernel_libipsec_ipsec.c \
|
||||||
kernel_libipsec_router.h kernel_libipsec_router.c
|
kernel_libipsec_router.h kernel_libipsec_router.c \
|
||||||
|
kernel_libipsec_esp_handler.h kernel_libipsec_esp_handler.c
|
||||||
|
|
||||||
libstrongswan_kernel_libipsec_la_LIBADD = $(top_builddir)/src/libipsec/libipsec.la
|
libstrongswan_kernel_libipsec_la_LIBADD = $(top_builddir)/src/libipsec/libipsec.la
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Tobias Brunner
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* for struct in6_pktinfo */
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include "kernel_libipsec_esp_handler.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
|
#include <ipsec.h>
|
||||||
|
#include <collections/blocking_queue.h>
|
||||||
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
|
typedef struct private_kernel_libipsec_esp_handler_t private_kernel_libipsec_esp_handler_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data
|
||||||
|
*/
|
||||||
|
struct private_kernel_libipsec_esp_handler_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface
|
||||||
|
*/
|
||||||
|
kernel_libipsec_esp_handler_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue for outbound ESP packets (esp_packet_t*)
|
||||||
|
*/
|
||||||
|
blocking_queue_t *queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Socket to send/receive IPv4 ESP packets
|
||||||
|
*/
|
||||||
|
int skt_v4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Socket to send/receive IPv6 ESP packets
|
||||||
|
*/
|
||||||
|
int skt_v6;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(kernel_libipsec_esp_handler_t, send_, void,
|
||||||
|
private_kernel_libipsec_esp_handler_t *this, esp_packet_t *packet)
|
||||||
|
{
|
||||||
|
this->queue->enqueue(this->queue, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(send_esp, job_requeue_t,
|
||||||
|
private_kernel_libipsec_esp_handler_t *this)
|
||||||
|
{
|
||||||
|
packet_t *packet;
|
||||||
|
host_t *source, *destination;
|
||||||
|
chunk_t data;
|
||||||
|
struct msghdr msg = {};
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
struct iovec iov;
|
||||||
|
char ancillary[64] = {};
|
||||||
|
ssize_t len;
|
||||||
|
int skt;
|
||||||
|
|
||||||
|
packet = (packet_t*)this->queue->dequeue(this->queue);
|
||||||
|
|
||||||
|
data = packet->get_data(packet);
|
||||||
|
source = packet->get_source(packet);
|
||||||
|
destination = packet->get_destination(packet);
|
||||||
|
DBG2(DBG_NET, "sending raw ESP packet: from %H to %H (%zu data bytes)",
|
||||||
|
source, destination, data.len);
|
||||||
|
|
||||||
|
/* the port of the destination address acts as protocol selector for RAW
|
||||||
|
* sockets, for IPv4 the kernel ignores it, for IPv6 it does not and
|
||||||
|
* complains if it isn't zero or doesn't match the one set on the socket */
|
||||||
|
destination->set_port(destination, 0);
|
||||||
|
|
||||||
|
msg.msg_name = destination->get_sockaddr(destination);
|
||||||
|
msg.msg_namelen = *destination->get_sockaddr_len(destination);
|
||||||
|
iov.iov_base = data.ptr;
|
||||||
|
iov.iov_len = data.len;
|
||||||
|
msg.msg_iov = &iov;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
msg.msg_control = ancillary;
|
||||||
|
|
||||||
|
if (source->get_family(source) == AF_INET)
|
||||||
|
{
|
||||||
|
struct in_pktinfo *pktinfo;
|
||||||
|
const struct sockaddr_in *sin;
|
||||||
|
|
||||||
|
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
|
||||||
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
cmsg->cmsg_level = IPPROTO_IP;
|
||||||
|
cmsg->cmsg_type = IP_PKTINFO;
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||||
|
|
||||||
|
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
sin = (struct sockaddr_in*)source->get_sockaddr(source);
|
||||||
|
memcpy(&pktinfo->ipi_spec_dst, &sin->sin_addr, sizeof(struct in_addr));
|
||||||
|
skt = this->skt_v4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct in6_pktinfo *pktinfo;
|
||||||
|
const struct sockaddr_in6 *sin;
|
||||||
|
|
||||||
|
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
|
||||||
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||||
|
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||||
|
|
||||||
|
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
sin = (struct sockaddr_in6*)source->get_sockaddr(source);
|
||||||
|
memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
|
||||||
|
skt = this->skt_v6;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sendmsg(skt, &msg, 0);
|
||||||
|
if (len != data.len)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "error writing to ESP socket: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
packet->destroy(packet);
|
||||||
|
return JOB_REQUEUE_DIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(receive_esp, bool,
|
||||||
|
private_kernel_libipsec_esp_handler_t *this, int fd, watcher_event_t event)
|
||||||
|
{
|
||||||
|
char buf[2048];
|
||||||
|
struct msghdr msg;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
struct iovec iov;
|
||||||
|
char ancillary[64];
|
||||||
|
union {
|
||||||
|
struct sockaddr_in in4;
|
||||||
|
struct sockaddr_in6 in6;
|
||||||
|
} src;
|
||||||
|
host_t *source, *destination = NULL;
|
||||||
|
packet_t *packet;
|
||||||
|
chunk_t data;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
msg.msg_name = &src;
|
||||||
|
msg.msg_namelen = sizeof(src);
|
||||||
|
iov.iov_base = buf;
|
||||||
|
iov.iov_len = sizeof(buf);
|
||||||
|
msg.msg_iov = &iov;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_control = ancillary;
|
||||||
|
msg.msg_controllen = sizeof(ancillary);
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
|
||||||
|
len = recvmsg(fd, &msg, MSG_DONTWAIT|MSG_TRUNC);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "receiving from ESP socket failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (msg.msg_flags & MSG_TRUNC)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "ESP packet with length %zd exceeds buffer size of %zu",
|
||||||
|
len, sizeof(buf));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
data = chunk_create(buf, len);
|
||||||
|
/* skip the IP header returned by IPv4 raw sockets */
|
||||||
|
if (fd == this->skt_v4)
|
||||||
|
{
|
||||||
|
data = chunk_skip(data, sizeof(struct iphdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||||
|
{
|
||||||
|
if (cmsg->cmsg_level == IPPROTO_IP &&
|
||||||
|
cmsg->cmsg_type == IP_PKTINFO)
|
||||||
|
{
|
||||||
|
const struct in_pktinfo *pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
struct sockaddr_in dst = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&dst.sin_addr, &pktinfo->ipi_addr, sizeof(dst.sin_addr));
|
||||||
|
destination = host_create_from_sockaddr((sockaddr_t*)&dst);
|
||||||
|
}
|
||||||
|
else if (cmsg->cmsg_level == IPPROTO_IPV6 &&
|
||||||
|
cmsg->cmsg_type == IPV6_PKTINFO)
|
||||||
|
{
|
||||||
|
const struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
struct sockaddr_in6 dst = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
|
||||||
|
destination = host_create_from_sockaddr((sockaddr_t*)&dst);
|
||||||
|
}
|
||||||
|
if (destination)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!destination)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "error reading destination IP address for ESP packet");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
source = host_create_from_sockaddr((sockaddr_t*)&src);
|
||||||
|
DBG2(DBG_NET, "received raw ESP packet: from %#H to %#H (%zu data bytes)",
|
||||||
|
source, destination, data.len);
|
||||||
|
|
||||||
|
packet = packet_create();
|
||||||
|
packet->set_source(packet, source);
|
||||||
|
packet->set_destination(packet, destination);
|
||||||
|
packet->set_data(packet, chunk_clone(data));
|
||||||
|
ipsec->processor->queue_inbound(ipsec->processor,
|
||||||
|
esp_packet_create_from_packet(packet));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_libipsec_esp_handler_t, destroy, void,
|
||||||
|
private_kernel_libipsec_esp_handler_t *this)
|
||||||
|
{
|
||||||
|
if (this->skt_v4 >= 0)
|
||||||
|
{
|
||||||
|
lib->watcher->remove(lib->watcher, this->skt_v4);
|
||||||
|
close(this->skt_v4);
|
||||||
|
}
|
||||||
|
if (this->skt_v6 >= 0)
|
||||||
|
{
|
||||||
|
lib->watcher->remove(lib->watcher, this->skt_v6);
|
||||||
|
close(this->skt_v6);
|
||||||
|
}
|
||||||
|
this->queue->destroy_offset(this->queue, offsetof(esp_packet_t, destroy));
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a RAW socket for the given address family
|
||||||
|
*/
|
||||||
|
static int create_socket(int family)
|
||||||
|
{
|
||||||
|
const char *fwmark;
|
||||||
|
mark_t mark;
|
||||||
|
int skt, on = 1;
|
||||||
|
|
||||||
|
skt = socket(family, SOCK_RAW, IPPROTO_ESP);
|
||||||
|
if (skt == -1)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "opening RAW socket for ESP failed: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (setsockopt(skt, family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
|
||||||
|
family == AF_INET ? IP_PKTINFO : IPV6_RECVPKTINFO,
|
||||||
|
&on, sizeof(on)) == -1)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to set PKTINFO on ESP socket: %s",
|
||||||
|
strerror(errno));
|
||||||
|
close(skt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fwmark = lib->settings->get_str(lib->settings,
|
||||||
|
"%s.plugins.kernel-libipsec.fwmark",
|
||||||
|
lib->settings->get_str(lib->settings,
|
||||||
|
"%s.plugins.socket-default.fwmark", NULL, lib->ns),
|
||||||
|
lib->ns);
|
||||||
|
if (fwmark && mark_from_string(fwmark, MARK_OP_NONE, &mark) &&
|
||||||
|
setsockopt(skt, SOL_SOCKET, SO_MARK, &mark.value, sizeof(mark.value)) < 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to set SO_MARK on ESP socket: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return skt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
kernel_libipsec_esp_handler_t *kernel_libipsec_esp_handler_create()
|
||||||
|
{
|
||||||
|
private_kernel_libipsec_esp_handler_t *this;
|
||||||
|
|
||||||
|
if (!lib->caps->keep(lib->caps, CAP_NET_RAW))
|
||||||
|
{ /* required to open SOCK_RAW sockets and according to capabilities(7)
|
||||||
|
* it is also required to use the socket */
|
||||||
|
DBG1(DBG_KNL, "kernel-libipsec requires CAP_NET_RAW capability to send "
|
||||||
|
"and receive ESP packets without UDP encapsulation");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.send = _send_,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
.queue = blocking_queue_create(),
|
||||||
|
.skt_v4 = create_socket(AF_INET),
|
||||||
|
.skt_v6 = create_socket(AF_INET6),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this->skt_v4 == -1 && this->skt_v6 == -1)
|
||||||
|
{
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (this->skt_v4 >= 0)
|
||||||
|
{
|
||||||
|
lib->watcher->add(lib->watcher, this->skt_v4, WATCHER_READ,
|
||||||
|
receive_esp, this);
|
||||||
|
}
|
||||||
|
if (this->skt_v6 >= 0)
|
||||||
|
{
|
||||||
|
lib->watcher->add(lib->watcher, this->skt_v6, WATCHER_READ,
|
||||||
|
receive_esp, this);
|
||||||
|
}
|
||||||
|
lib->processor->queue_job(lib->processor,
|
||||||
|
(job_t*)callback_job_create(send_esp, this, NULL,
|
||||||
|
(callback_job_cancel_t)return_false));
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* __linux__ */
|
||||||
|
|
||||||
|
kernel_libipsec_esp_handler_t *kernel_libipsec_esp_handler_create()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __linux__ */
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Tobias Brunner
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup kernel_libipsec_esp_handler kernel_libipsec_esp_handler
|
||||||
|
* @{ @ingroup kernel_libipsec
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KERNEL_LIBIPSEC_ESP_HANDLER_H_
|
||||||
|
#define KERNEL_LIBIPSEC_ESP_HANDLER_H_
|
||||||
|
|
||||||
|
#include <esp_packet.h>
|
||||||
|
|
||||||
|
typedef struct kernel_libipsec_esp_handler_t kernel_libipsec_esp_handler_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that sends and receives raw ESP packets.
|
||||||
|
*/
|
||||||
|
struct kernel_libipsec_esp_handler_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given ESP packet without UDP encapsulation.
|
||||||
|
*
|
||||||
|
* @param packet ESP packet to send
|
||||||
|
*/
|
||||||
|
void (*send)(kernel_libipsec_esp_handler_t *this, esp_packet_t *packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the given instance.
|
||||||
|
*/
|
||||||
|
void (*destroy)(kernel_libipsec_esp_handler_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a kernel_libipsec_esp_handler_t instance.
|
||||||
|
*
|
||||||
|
* @return created instance, NULL if not supported
|
||||||
|
*/
|
||||||
|
kernel_libipsec_esp_handler_t *kernel_libipsec_esp_handler_create();
|
||||||
|
|
||||||
|
#endif /** KERNEL_LIBIPSEC_ESP_HANDLER_H_ @}*/
|
||||||
@@ -56,6 +56,11 @@ struct private_kernel_libipsec_ipsec_t {
|
|||||||
* Whether the remote TS may equal the IKE peer
|
* Whether the remote TS may equal the IKE peer
|
||||||
*/
|
*/
|
||||||
bool allow_peer_ts;
|
bool allow_peer_ts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether UDP encapsulation is required
|
||||||
|
*/
|
||||||
|
bool require_encap;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct exclude_route_t exclude_route_t;
|
typedef struct exclude_route_t exclude_route_t;
|
||||||
@@ -241,8 +246,8 @@ static void acquire(uint32_t reqid)
|
|||||||
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||||
private_kernel_libipsec_ipsec_t *this)
|
private_kernel_libipsec_ipsec_t *this)
|
||||||
{
|
{
|
||||||
return KERNEL_REQUIRE_UDP_ENCAPSULATION | KERNEL_ESP_V3_TFC |
|
return KERNEL_ESP_V3_TFC | KERNEL_SA_USE_TIME |
|
||||||
KERNEL_SA_USE_TIME;
|
(this->require_encap ? KERNEL_REQUIRE_UDP_ENCAPSULATION : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_spi, status_t,
|
METHOD(kernel_ipsec_t, get_spi, status_t,
|
||||||
@@ -263,6 +268,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||||
kernel_ipsec_add_sa_t *data)
|
kernel_ipsec_add_sa_t *data)
|
||||||
{
|
{
|
||||||
|
if (this->require_encap && !data->encap)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ESP, "failed to add SAD entry: only UDP encapsulation is "
|
||||||
|
"supported");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
|
||||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||||
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
data->enc_alg, data->enc_key, data->int_alg, data->int_key,
|
||||||
@@ -698,6 +709,7 @@ kernel_libipsec_ipsec_t *kernel_libipsec_ipsec_create()
|
|||||||
.excludes = linked_list_create(),
|
.excludes = linked_list_create(),
|
||||||
.allow_peer_ts = lib->settings->get_bool(lib->settings,
|
.allow_peer_ts = lib->settings->get_bool(lib->settings,
|
||||||
"%s.plugins.kernel-libipsec.allow_peer_ts", FALSE, lib->ns),
|
"%s.plugins.kernel-libipsec.allow_peer_ts", FALSE, lib->ns),
|
||||||
|
.require_encap = !lib->get(lib, "kernel-libipsec-esp-handler"),
|
||||||
);
|
);
|
||||||
|
|
||||||
ipsec->events->register_listener(ipsec->events, &this->ipsec_listener);
|
ipsec->events->register_listener(ipsec->events, &this->ipsec_listener);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2013 Tobias Brunner
|
* Copyright (C) 2012-2023 Tobias Brunner
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
*
|
*
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "kernel_libipsec_plugin.h"
|
#include "kernel_libipsec_plugin.h"
|
||||||
#include "kernel_libipsec_ipsec.h"
|
#include "kernel_libipsec_ipsec.h"
|
||||||
#include "kernel_libipsec_router.h"
|
#include "kernel_libipsec_router.h"
|
||||||
|
#include "kernel_libipsec_esp_handler.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <ipsec.h>
|
#include <ipsec.h>
|
||||||
@@ -45,6 +46,11 @@ struct private_kernel_libipsec_plugin_t {
|
|||||||
* Packet router
|
* Packet router
|
||||||
*/
|
*/
|
||||||
kernel_libipsec_router_t *router;
|
kernel_libipsec_router_t *router;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw ESP handler
|
||||||
|
*/
|
||||||
|
kernel_libipsec_esp_handler_t *esp_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(plugin_t, get_name, char*,
|
METHOD(plugin_t, get_name, char*,
|
||||||
@@ -92,6 +98,11 @@ METHOD(plugin_t, destroy, void,
|
|||||||
lib->set(lib, "kernel-libipsec-tun", NULL);
|
lib->set(lib, "kernel-libipsec-tun", NULL);
|
||||||
this->tun->destroy(this->tun);
|
this->tun->destroy(this->tun);
|
||||||
}
|
}
|
||||||
|
if (this->esp_handler)
|
||||||
|
{
|
||||||
|
lib->set(lib, "kernel-libipsec-esp-handler", NULL);
|
||||||
|
this->esp_handler->destroy(this->esp_handler);
|
||||||
|
}
|
||||||
libipsec_deinit();
|
libipsec_deinit();
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -146,5 +157,17 @@ plugin_t *kernel_libipsec_plugin_create()
|
|||||||
/* set TUN device as default to install VIPs */
|
/* set TUN device as default to install VIPs */
|
||||||
lib->settings->set_str(lib->settings, "%s.install_virtual_ip_on",
|
lib->settings->set_str(lib->settings, "%s.install_virtual_ip_on",
|
||||||
this->tun->get_name(this->tun), lib->ns);
|
this->tun->get_name(this->tun), lib->ns);
|
||||||
|
|
||||||
|
if (lib->settings->get_bool(lib->settings,
|
||||||
|
"%s.plugins.kernel-libipsec.raw_esp", FALSE, lib->ns))
|
||||||
|
{
|
||||||
|
this->esp_handler = kernel_libipsec_esp_handler_create();
|
||||||
|
if (!this->esp_handler)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "only UDP-encapsulated ESP packets supported by "
|
||||||
|
"kernel-libipsec on this platform");
|
||||||
|
}
|
||||||
|
lib->set(lib, "kernel-libipsec-esp-handler", this->esp_handler);
|
||||||
|
}
|
||||||
return &this->public.plugin;
|
return &this->public.plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "kernel_libipsec_router.h"
|
#include "kernel_libipsec_router.h"
|
||||||
|
#include "kernel_libipsec_esp_handler.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <ipsec.h>
|
#include <ipsec.h>
|
||||||
@@ -76,6 +77,11 @@ struct private_kernel_libipsec_router_t {
|
|||||||
* Pipe to signal handle_plain() about changes regarding TUN devices
|
* Pipe to signal handle_plain() about changes regarding TUN devices
|
||||||
*/
|
*/
|
||||||
int notify[2];
|
int notify[2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESP handler to send raw ESP packets
|
||||||
|
*/
|
||||||
|
kernel_libipsec_esp_handler_t *esp_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,28 +100,32 @@ static bool tun_entry_equals(tun_entry_t *a, tun_entry_t *b)
|
|||||||
return a->addr->ip_equals(a->addr, b->addr);
|
return a->addr->ip_equals(a->addr, b->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(send_esp, void,
|
||||||
* Outbound callback
|
private_kernel_libipsec_router_t *this, esp_packet_t *packet, bool encap)
|
||||||
*/
|
|
||||||
static void send_esp(void *data, esp_packet_t *packet)
|
|
||||||
{
|
{
|
||||||
charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
|
if (encap)
|
||||||
|
{
|
||||||
|
charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
|
||||||
|
}
|
||||||
|
else if (this->esp_handler)
|
||||||
|
{
|
||||||
|
this->esp_handler->send(this->esp_handler, packet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* shouldn't happen as UDP encap is forced without ESP handler */
|
||||||
|
packet->destroy(packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(receiver_esp_cb, void,
|
||||||
* Receiver callback
|
void *data, packet_t *packet)
|
||||||
*/
|
|
||||||
static void receiver_esp_cb(void *data, packet_t *packet)
|
|
||||||
{
|
{
|
||||||
ipsec->processor->queue_inbound(ipsec->processor,
|
ipsec->processor->queue_inbound(ipsec->processor,
|
||||||
esp_packet_create_from_packet(packet));
|
esp_packet_create_from_packet(packet));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CALLBACK(deliver_plain, void,
|
||||||
* Inbound callback
|
private_kernel_libipsec_router_t *this, ip_packet_t *packet)
|
||||||
*/
|
|
||||||
static void deliver_plain(private_kernel_libipsec_router_t *this,
|
|
||||||
ip_packet_t *packet)
|
|
||||||
{
|
{
|
||||||
tun_device_t *tun;
|
tun_device_t *tun;
|
||||||
tun_entry_t *entry, lookup = {
|
tun_entry_t *entry, lookup = {
|
||||||
@@ -292,12 +302,9 @@ METHOD(kernel_libipsec_router_t, get_tun_name, char*,
|
|||||||
METHOD(kernel_libipsec_router_t, destroy, void,
|
METHOD(kernel_libipsec_router_t, destroy, void,
|
||||||
private_kernel_libipsec_router_t *this)
|
private_kernel_libipsec_router_t *this)
|
||||||
{
|
{
|
||||||
charon->receiver->del_esp_cb(charon->receiver,
|
charon->receiver->del_esp_cb(charon->receiver, receiver_esp_cb);
|
||||||
(receiver_esp_cb_t)receiver_esp_cb);
|
ipsec->processor->unregister_outbound(ipsec->processor, send_esp);
|
||||||
ipsec->processor->unregister_outbound(ipsec->processor,
|
ipsec->processor->unregister_inbound(ipsec->processor, deliver_plain);
|
||||||
(ipsec_outbound_cb_t)send_esp);
|
|
||||||
ipsec->processor->unregister_inbound(ipsec->processor,
|
|
||||||
(ipsec_inbound_cb_t)deliver_plain);
|
|
||||||
charon->kernel->remove_listener(charon->kernel, &this->public.listener);
|
charon->kernel->remove_listener(charon->kernel, &this->public.listener);
|
||||||
this->lock->destroy(this->lock);
|
this->lock->destroy(this->lock);
|
||||||
this->tuns->destroy(this->tuns);
|
this->tuns->destroy(this->tuns);
|
||||||
@@ -333,7 +340,8 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
|
|||||||
},
|
},
|
||||||
.tun = {
|
.tun = {
|
||||||
.tun = lib->get(lib, "kernel-libipsec-tun"),
|
.tun = lib->get(lib, "kernel-libipsec-tun"),
|
||||||
}
|
},
|
||||||
|
.esp_handler = lib->get(lib, "kernel-libipsec-esp-handler"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pipe(this->notify) != 0 ||
|
if (pipe(this->notify) != 0 ||
|
||||||
@@ -351,11 +359,9 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
|
|||||||
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
|
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
|
||||||
|
|
||||||
charon->kernel->add_listener(charon->kernel, &this->public.listener);
|
charon->kernel->add_listener(charon->kernel, &this->public.listener);
|
||||||
ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL);
|
ipsec->processor->register_outbound(ipsec->processor, send_esp, this);
|
||||||
ipsec->processor->register_inbound(ipsec->processor,
|
ipsec->processor->register_inbound(ipsec->processor, deliver_plain, this);
|
||||||
(ipsec_inbound_cb_t)deliver_plain, this);
|
charon->receiver->add_esp_cb(charon->receiver, receiver_esp_cb, NULL);
|
||||||
charon->receiver->add_esp_cb(charon->receiver,
|
|
||||||
(receiver_esp_cb_t)receiver_esp_cb, NULL);
|
|
||||||
lib->processor->queue_job(lib->processor,
|
lib->processor->queue_job(lib->processor,
|
||||||
(job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
|
(job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
|
||||||
NULL, (callback_job_cancel_t)return_false));
|
NULL, (callback_job_cancel_t)return_false));
|
||||||
|
|||||||
@@ -169,12 +169,12 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
* Send an ESP packet using the registered outbound callback
|
* Send an ESP packet using the registered outbound callback
|
||||||
*/
|
*/
|
||||||
static void send_outbound(private_ipsec_processor_t *this,
|
static void send_outbound(private_ipsec_processor_t *this,
|
||||||
esp_packet_t *packet)
|
esp_packet_t *packet, bool encap)
|
||||||
{
|
{
|
||||||
this->lock->read_lock(this->lock);
|
this->lock->read_lock(this->lock);
|
||||||
if (this->outbound.cb)
|
if (this->outbound.cb)
|
||||||
{
|
{
|
||||||
this->outbound.cb(this->outbound.data, packet);
|
this->outbound.cb(this->outbound.data, packet, encap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -194,7 +194,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
|||||||
ip_packet_t *packet;
|
ip_packet_t *packet;
|
||||||
ipsec_sa_t *sa;
|
ipsec_sa_t *sa;
|
||||||
host_t *src, *dst;
|
host_t *src, *dst;
|
||||||
bool acquire = FALSE;
|
bool acquire = FALSE, encap = FALSE;
|
||||||
|
|
||||||
packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue);
|
packet = (ip_packet_t*)this->outbound_queue->dequeue(this->outbound_queue);
|
||||||
|
|
||||||
@@ -242,9 +242,10 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
|||||||
return JOB_REQUEUE_DIRECT;
|
return JOB_REQUEUE_DIRECT;
|
||||||
}
|
}
|
||||||
sa->update_usestats(sa, packet->get_encoding(packet).len);
|
sa->update_usestats(sa, packet->get_encoding(packet).len);
|
||||||
|
encap = sa->get_encap(sa);
|
||||||
ipsec->sas->checkin(ipsec->sas, sa);
|
ipsec->sas->checkin(ipsec->sas, sa);
|
||||||
policy->destroy(policy);
|
policy->destroy(policy);
|
||||||
send_outbound(this, esp_packet);
|
send_outbound(this, esp_packet, encap);
|
||||||
return JOB_REQUEUE_DIRECT;
|
return JOB_REQUEUE_DIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 Tobias Brunner
|
* Copyright (C) 2012-2023 Tobias Brunner
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
*
|
*
|
||||||
@@ -43,8 +43,10 @@ typedef void (*ipsec_inbound_cb_t)(void *data, ip_packet_t *packet);
|
|||||||
*
|
*
|
||||||
* @param data data supplied during registration of the callback
|
* @param data data supplied during registration of the callback
|
||||||
* @param packet ESP packet to send
|
* @param packet ESP packet to send
|
||||||
|
* @param encap TRUE to send the packet with UDP encapsulation
|
||||||
*/
|
*/
|
||||||
typedef void (*ipsec_outbound_cb_t)(void *data, esp_packet_t *packet);
|
typedef void (*ipsec_outbound_cb_t)(void *data, esp_packet_t *packet,
|
||||||
|
bool encap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPsec processor
|
* IPsec processor
|
||||||
|
|||||||
+21
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 Tobias Brunner
|
* Copyright (C) 2012-2023 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
*
|
*
|
||||||
@@ -69,6 +69,11 @@ struct private_ipsec_sa_t {
|
|||||||
*/
|
*/
|
||||||
ipsec_mode_t mode;
|
ipsec_mode_t mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRUE if UDP encapsulation should be used when sending
|
||||||
|
*/
|
||||||
|
bool encap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TRUE if extended sequence numbers are used
|
* TRUE if extended sequence numbers are used
|
||||||
*/
|
*/
|
||||||
@@ -133,6 +138,18 @@ METHOD(ipsec_sa_t, set_destination, void,
|
|||||||
this->dst = addr->clone(addr);
|
this->dst = addr->clone(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_t, get_encap, bool,
|
||||||
|
private_ipsec_sa_t *this)
|
||||||
|
{
|
||||||
|
return this->encap;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_t, set_encap, void,
|
||||||
|
private_ipsec_sa_t *this, bool encap)
|
||||||
|
{
|
||||||
|
this->encap = encap;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(ipsec_sa_t, get_spi, uint32_t,
|
METHOD(ipsec_sa_t, get_spi, uint32_t,
|
||||||
private_ipsec_sa_t *this)
|
private_ipsec_sa_t *this)
|
||||||
{
|
{
|
||||||
@@ -285,11 +302,6 @@ ipsec_sa_t *ipsec_sa_create(uint32_t spi, host_t *src, host_t *dst,
|
|||||||
DBG1(DBG_ESP, " IPsec SA: protocol not supported");
|
DBG1(DBG_ESP, " IPsec SA: protocol not supported");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!encap)
|
|
||||||
{
|
|
||||||
DBG1(DBG_ESP, " IPsec SA: only UDP encapsulation is supported");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (esn)
|
if (esn)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ESP, " IPsec SA: ESN not supported");
|
DBG1(DBG_ESP, " IPsec SA: ESN not supported");
|
||||||
@@ -313,6 +325,8 @@ ipsec_sa_t *ipsec_sa_create(uint32_t spi, host_t *src, host_t *dst,
|
|||||||
.get_destination = _get_destination,
|
.get_destination = _get_destination,
|
||||||
.set_source = _set_source,
|
.set_source = _set_source,
|
||||||
.set_destination = _set_destination,
|
.set_destination = _set_destination,
|
||||||
|
.get_encap = _get_encap,
|
||||||
|
.set_encap = _set_encap,
|
||||||
.get_spi = _get_spi,
|
.get_spi = _get_spi,
|
||||||
.get_reqid = _get_reqid,
|
.get_reqid = _get_reqid,
|
||||||
.get_protocol = _get_protocol,
|
.get_protocol = _get_protocol,
|
||||||
@@ -333,6 +347,7 @@ ipsec_sa_t *ipsec_sa_create(uint32_t spi, host_t *src, host_t *dst,
|
|||||||
.protocol = protocol,
|
.protocol = protocol,
|
||||||
.reqid = reqid,
|
.reqid = reqid,
|
||||||
.mode = mode,
|
.mode = mode,
|
||||||
|
.encap = encap,
|
||||||
.esn = esn,
|
.esn = esn,
|
||||||
.inbound = inbound,
|
.inbound = inbound,
|
||||||
);
|
);
|
||||||
|
|||||||
+15
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 Tobias Brunner
|
* Copyright (C) 2012-2023 Tobias Brunner
|
||||||
* Copyright (C) 2012 Giuliano Grassi
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
* Copyright (C) 2012 Ralf Sager
|
* Copyright (C) 2012 Ralf Sager
|
||||||
*
|
*
|
||||||
@@ -66,6 +66,20 @@ struct ipsec_sa_t {
|
|||||||
*/
|
*/
|
||||||
void (*set_destination)(ipsec_sa_t *this, host_t *addr);
|
void (*set_destination)(ipsec_sa_t *this, host_t *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether UDP encapsulation should be used for this SA
|
||||||
|
*
|
||||||
|
* @return TRUE if encapsulation should be used, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*get_encap)(ipsec_sa_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether UDP encapsulation should be used for this SA
|
||||||
|
*
|
||||||
|
* @param encap TRUE if encapsulation should be used, FALSE otherwise
|
||||||
|
*/
|
||||||
|
void (*set_encap)(ipsec_sa_t *this, bool encap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the SPI for this SA
|
* Get the SPI for this SA
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ METHOD(ipsec_sa_mgr_t, get_spi, status_t,
|
|||||||
|
|
||||||
METHOD(ipsec_sa_mgr_t, add_sa, status_t,
|
METHOD(ipsec_sa_mgr_t, add_sa, status_t,
|
||||||
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, uint32_t spi,
|
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, uint32_t spi,
|
||||||
uint8_t protocol, uint32_t reqid, mark_t mark, uint32_t tfc,
|
uint8_t protocol, uint32_t reqid, mark_t mark, uint32_t tfc,
|
||||||
lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
|
||||||
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode, uint16_t ipcomp,
|
uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode, uint16_t ipcomp,
|
||||||
uint16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
|
uint16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
|
||||||
@@ -568,13 +568,6 @@ METHOD(ipsec_sa_mgr_t, update_sa, status_t,
|
|||||||
DBG2(DBG_ESP, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
|
DBG2(DBG_ESP, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
|
||||||
ntohl(spi), src, dst, new_src, new_dst);
|
ntohl(spi), src, dst, new_src, new_dst);
|
||||||
|
|
||||||
if (!new_encap)
|
|
||||||
{
|
|
||||||
DBG1(DBG_ESP, "failed to update SAD entry: can't deactivate UDP "
|
|
||||||
"encapsulation");
|
|
||||||
return NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
if (this->sas->find_first(this->sas, match_entry_by_spi_src_dst_cb,
|
if (this->sas->find_first(this->sas, match_entry_by_spi_src_dst_cb,
|
||||||
(void**)&entry, spi, src, dst) &&
|
(void**)&entry, spi, src, dst) &&
|
||||||
@@ -582,6 +575,7 @@ METHOD(ipsec_sa_mgr_t, update_sa, status_t,
|
|||||||
{
|
{
|
||||||
entry->sa->set_source(entry->sa, new_src);
|
entry->sa->set_source(entry->sa, new_src);
|
||||||
entry->sa->set_destination(entry->sa, new_dst);
|
entry->sa->set_destination(entry->sa, new_dst);
|
||||||
|
entry->sa->set_encap(entry->sa, new_encap);
|
||||||
/* checkin the entry */
|
/* checkin the entry */
|
||||||
entry->locked = FALSE;
|
entry->locked = FALSE;
|
||||||
entry->condvar->signal(entry->condvar);
|
entry->condvar->signal(entry->condvar);
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
A connection between the hosts <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
The authentication is based on <b>X.509 certificates</b> and the <b>kernel-libipsec</b>
|
||||||
|
plugin is used for userland IPsec ESP encryption. In this scenario, UDP encapsulation
|
||||||
|
isn't enforced by the plugin as sending of raw ESP packets is enabled.
|
||||||
|
<b>Firewall marks</b> are used to make the direct ESP connection possible and
|
||||||
|
still allow IKE traffic to flow freely between the two hosts.
|
||||||
|
<p/>
|
||||||
|
Upon the successful establishment of the IPsec tunnel, an updown script automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the traffic tunneled via the
|
||||||
|
<b>ipsec0</b> tun interface. In order to test both host-to-host tunnel and firewall,
|
||||||
|
<b>moon</b> pings <b>sun</b>.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
||||||
|
moon::swanctl --list-sas --raw 2> /dev/null::host-host.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*host-host.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.1/32] remote-ts=\[192.168.0.2/32]::YES
|
||||||
|
sun::swanctl --list-sas --raw 2> /dev/null::host-host.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*host-host.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.2/32] remote-ts=\[192.168.0.1/32]::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown
|
||||||
|
|
||||||
|
multiple_authentication = no
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kernel-netlink {
|
||||||
|
fwmark = !0x42
|
||||||
|
}
|
||||||
|
socket-default {
|
||||||
|
fwmark = 0x42
|
||||||
|
}
|
||||||
|
kernel-libipsec {
|
||||||
|
allow_peer_ts = yes
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
host-host {
|
||||||
|
local_addrs = 192.168.0.1
|
||||||
|
remote_addrs = 192.168.0.2
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = moonCert.pem
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
host-host {
|
||||||
|
updown = /etc/updown
|
||||||
|
esp_proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-host)
|
||||||
|
iptables -I OUTPUT 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -I INPUT 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-host)
|
||||||
|
iptables -D OUTPUT -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -D INPUT -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown
|
||||||
|
|
||||||
|
multiple_authentication = no
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kernel-netlink {
|
||||||
|
fwmark = !0x42
|
||||||
|
}
|
||||||
|
socket-default {
|
||||||
|
fwmark = 0x42
|
||||||
|
}
|
||||||
|
kernel-libipsec {
|
||||||
|
allow_peer_ts = yes
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
host-host {
|
||||||
|
local_addrs = 192.168.0.2
|
||||||
|
remote_addrs = 192.168.0.1
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = sunCert.pem
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
host-host {
|
||||||
|
updown = /etc/updown
|
||||||
|
esp_proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-host)
|
||||||
|
iptables -I OUTPUT 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -I INPUT 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-host)
|
||||||
|
iptables -D OUTPUT -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -D INPUT -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
moon::swanctl --terminate --ike host-host 2> /dev/null
|
||||||
|
moon::systemctl stop strongswan
|
||||||
|
sun::systemctl stop strongswan
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
|
moon::sysctl --pattern net.ipv4.conf.all.rp_filter --system
|
||||||
|
sun::sysctl --pattern net.ipv4.conf.all.rp_filter --system
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
moon::sysctl -w net.ipv4.conf.all.rp_filter=2
|
||||||
|
sun::sysctl -w net.ipv4.conf.all.rp_filter=2
|
||||||
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
|
moon::systemctl start strongswan
|
||||||
|
sun::systemctl start strongswan
|
||||||
|
sun::expect-connection host-host
|
||||||
|
moon::expect-connection host-host
|
||||||
|
moon::swanctl --initiate --child host-host 2> /dev/null
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="moon winnetou sun"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="m-w-s.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
|
|
||||||
|
# charon controlled by swanctl
|
||||||
|
#
|
||||||
|
SWANCTL=1
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
alice::ping6 -c 3 -W 1 -i 0.2 -s 8184 -p deadbeef ip6-bob.strongswan.org::8192 bytes from ip6-bob.strongswan.org.*: icmp_seq=3::YES
|
alice::ping6 -c 3 -W 1 -i 0.2 -s 8184 -p deadbeef ip6-bob.strongswan.org::8192 bytes from ip6-bob.strongswan.org.*: icmp_seq=3::YES
|
||||||
moon ::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=256 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=ECP_384.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=256.*local-ts=\[fec1::/16\[ipv6-icmp]] remote-ts=\[fec2::/16\[ipv6-icmp]]::YES
|
moon ::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=256 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=ECP_384.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=256.*local-ts=\[fec1:\:/16\[ipv6-icmp]] remote-ts=\[fec2:\:/16\[ipv6-icmp]]::YES
|
||||||
sun ::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=256 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=ECP_384.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=256.*local-ts=\[fec2::/16\[ipv6-icmp]] remote-ts=\[fec1::/16\[ipv6-icmp]]::YES
|
sun ::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=256 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=ECP_384.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=256.*local-ts=\[fec2:\:/16\[ipv6-icmp]] remote-ts=\[fec1:\:/16\[ipv6-icmp]]::YES
|
||||||
sun::tcpdump::IP moon.strongswan.org.\(4500\|ipsec-nat-t\) > sun.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES
|
sun::tcpdump::IP moon.strongswan.org.\(4500\|ipsec-nat-t\) > sun.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES
|
||||||
sun::tcpdump::IP sun.strongswan.org.\(4500\|ipsec-nat-t\) > moon.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES
|
sun::tcpdump::IP sun.strongswan.org.\(4500\|ipsec-nat-t\) > moon.strongswan.org.\(4500\|ipsec-nat-t\): UDP-encap: ESP::YES
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
An IPv6 ESP tunnel connection between the gateways <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
It connects the two IPv6 subnets hiding behind their respective gateways.
|
||||||
|
The authentication is based on <b>X.509 certificates</b> and the <b>kernel-libipsec</b>
|
||||||
|
plugin is used for userland IPsec ESP encryption. In this scenario, UDP encapsulation
|
||||||
|
isn't enforced by the plugin as sending of raw ESP packets is enabled.
|
||||||
|
<p/>
|
||||||
|
Upon the successful establishment of the IPsec tunnel, an updown script automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the traffic tunneled via the
|
||||||
|
<b>ipsec0</b> tun interface. In order to test both tunnel and firewall, client <b>alice</b>
|
||||||
|
behind gateway <b>moon</b> sends an IPv6 ICMP request to client <b>bob</b> behind <b>sun</b>
|
||||||
|
using the ping6 command.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alice::ping6 -c 1 -p deadbeef ip6-bob.strongswan.org::64 bytes from ip6-bob.strongswan.org.*: icmp_seq=1::YES
|
||||||
|
moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=fec0:\:1 local-port=500 local-id=moon.strongswan.org remote-host=fec0:\:2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[fec1:\:/16] remote-ts=\[fec2:\:/16]::YES
|
||||||
|
sun ::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=fec0:\:2 local-port=500 local-id=sun.strongswan.org remote-host=fec0:\:1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[fec2:\:/16] remote-ts=\[fec1:\:/16]::YES
|
||||||
|
sun::tcpdump::IP6 ip6-moon.strongswan.org > ip6-sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP6 ip6-sun.strongswan.org > ip6-moon.strongswan.org: ESP::YES
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown
|
||||||
|
multiple_authentication = no
|
||||||
|
plugins {
|
||||||
|
kernel-libipsec {
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = fec0::1
|
||||||
|
remote_addrs = fec0::2
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = moonCert.pem
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = fec1::0/16
|
||||||
|
remote_ts = fec2::0/16
|
||||||
|
|
||||||
|
updown = /etc/updown
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authorities {
|
||||||
|
strongswan {
|
||||||
|
cacert = strongswanCert.pem
|
||||||
|
crl_uris = http://ip6-winnetou.strongswan.org/strongswan.crl
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-client-v6)
|
||||||
|
ip6tables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
ip6tables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-client-v6)
|
||||||
|
ip6tables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
ip6tables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici ker_nel-libipsec kernel-netlink socket-default updown
|
||||||
|
multiple_authentication = no
|
||||||
|
plugins {
|
||||||
|
kernel-libipsec {
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = fec0::2
|
||||||
|
remote_addrs = fec0::1
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = sunCert.pem
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = fec2::0/16
|
||||||
|
remote_ts = fec1::0/16
|
||||||
|
|
||||||
|
updown = /etc/updown
|
||||||
|
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authorities {
|
||||||
|
strongswan {
|
||||||
|
cacert = strongswanCert.pem
|
||||||
|
crl_uris = http://ip6-winnetou.strongswan.org/strongswan.crl
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-client-v6)
|
||||||
|
ip6tables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
ip6tables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-client-v6)
|
||||||
|
ip6tables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
ip6tables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
moon::swanctl --terminate --ike gw-gw 2> /dev/null
|
||||||
|
moon::systemctl stop strongswan
|
||||||
|
sun::systemctl stop strongswan
|
||||||
|
alice::"ip route del fec2:\:/16 via fec1:\:1"
|
||||||
|
moon::"ip route del fec2:\:/16 via fec0:\:2"
|
||||||
|
sun::"ip route del fec1:\:/16 via fec0:\:1"
|
||||||
|
bob::"ip route del fec1:\:/16 via fec2:\:1"
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
|
moon::ip6tables-restore < /etc/ip6tables.flush
|
||||||
|
sun::ip6tables-restore < /etc/ip6tables.flush
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
moon::iptables-restore < /etc/iptables.drop
|
||||||
|
sun::iptables-restore < /etc/iptables.drop
|
||||||
|
moon::ip6tables-restore < /etc/ip6tables.rules
|
||||||
|
sun::ip6tables-restore < /etc/ip6tables.rules
|
||||||
|
alice::"ip route add fec2:\:/16 via fec1:\:1"
|
||||||
|
moon::"ip route add fec2:\:/16 via fec0:\:2"
|
||||||
|
sun::"ip route add fec1:\:/16 via fec0:\:1"
|
||||||
|
bob::"ip route add fec1:\:/16 via fec2:\:1"
|
||||||
|
moon::systemctl start strongswan
|
||||||
|
sun::systemctl start strongswan
|
||||||
|
moon::expect-connection gw-gw
|
||||||
|
sun::expect-connection gw-gw
|
||||||
|
moon::swanctl --initiate --child net-net 2> /dev/null
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="alice moon winnetou sun bob"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="a-m-w-s-b-ip6.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
|
|
||||||
|
# IP protocol used by IPsec is IPv6
|
||||||
|
#
|
||||||
|
IPV6=1
|
||||||
|
|
||||||
|
# charon controlled by swanctl
|
||||||
|
#
|
||||||
|
SWANCTL=1
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
The authentication is based on <b>X.509 certificates</b> and the <b>kernel-libipsec</b>
|
||||||
|
plugin is used for userland IPsec ESP encryption. In this scenario, UDP encapsulation
|
||||||
|
isn't enforced by the plugin as sending of raw ESP packets is enabled.
|
||||||
|
<p/>
|
||||||
|
Upon the successful establishment of the IPsec tunnel, an updown script automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the traffic tunneled via the
|
||||||
|
<b>ipsec0</b> tun interface. In order to test both tunnel and firewall, client <b>alice</b>
|
||||||
|
behind gateway <b>moon</b> pings client <b>bob</b> located behind gateway <b>sun</b>.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
|
||||||
|
moon:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
|
||||||
|
sun::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=CURVE_25519.*child-sas.*net-net.*reqid=1 state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-libipsec kernel-netlink socket-default updown
|
||||||
|
multiple_authentication = no
|
||||||
|
plugins {
|
||||||
|
kernel-libipsec {
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = 192.168.0.1
|
||||||
|
remote_addrs = 192.168.0.2
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = moonCert.pem
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = 10.1.0.0/16
|
||||||
|
remote_ts = 10.2.0.0/16
|
||||||
|
|
||||||
|
updown = /etc/updown
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-client)
|
||||||
|
iptables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-client)
|
||||||
|
iptables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
swanctl {
|
||||||
|
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||||
|
}
|
||||||
|
|
||||||
|
charon-systemd {
|
||||||
|
load = random nonce aes sha1 sha2 gcm pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici ker_nel-libipsec kernel-netlink socket-default updown
|
||||||
|
multiple_authentication = no
|
||||||
|
plugins {
|
||||||
|
kernel-libipsec {
|
||||||
|
raw_esp = yes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
connections {
|
||||||
|
|
||||||
|
gw-gw {
|
||||||
|
local_addrs = 192.168.0.2
|
||||||
|
remote_addrs = 192.168.0.1
|
||||||
|
|
||||||
|
local {
|
||||||
|
auth = pubkey
|
||||||
|
certs = sunCert.pem
|
||||||
|
id = sun.strongswan.org
|
||||||
|
}
|
||||||
|
remote {
|
||||||
|
auth = pubkey
|
||||||
|
id = moon.strongswan.org
|
||||||
|
}
|
||||||
|
children {
|
||||||
|
net-net {
|
||||||
|
local_ts = 10.2.0.0/16
|
||||||
|
remote_ts = 10.1.0.0/16
|
||||||
|
|
||||||
|
updown = /etc/updown
|
||||||
|
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||||
|
esp_proposals = aes128gcm128-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = 2
|
||||||
|
mobike = no
|
||||||
|
proposals = aes128-sha256-x25519
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TUN_NAME=ipsec0
|
||||||
|
|
||||||
|
# use protocol specific options to set ports
|
||||||
|
case "$PLUTO_MY_PROTOCOL" in
|
||||||
|
1) # ICMP
|
||||||
|
ICMP_TYPE_OPTION="--icmp-type"
|
||||||
|
;;
|
||||||
|
58) # ICMPv6
|
||||||
|
ICMP_TYPE_OPTION="--icmpv6-type"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# are there port numbers?
|
||||||
|
if [ "$PLUTO_MY_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
S_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="$ICMP_TYPE_OPTION $PLUTO_MY_PORT"
|
||||||
|
else
|
||||||
|
S_MY_PORT="--sport $PLUTO_MY_PORT"
|
||||||
|
D_MY_PORT="--dport $PLUTO_MY_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$PLUTO_PEER_PORT" != 0 ]
|
||||||
|
then
|
||||||
|
if [ -n "$ICMP_TYPE_OPTION" ]
|
||||||
|
then
|
||||||
|
# the syntax is --icmp[v6]-type type[/code], so add it to the existing option
|
||||||
|
S_MY_PORT="$S_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
D_MY_PORT="$D_MY_PORT/$PLUTO_PEER_PORT"
|
||||||
|
else
|
||||||
|
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
|
||||||
|
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$PLUTO_VERB" in
|
||||||
|
up-client)
|
||||||
|
iptables -I FORWARD 1 -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
down-client)
|
||||||
|
iptables -D FORWARD -o $TUN_NAME -p $PLUTO_PEER_PROTOCOL \
|
||||||
|
-s $PLUTO_MY_CLIENT $S_MY_PORT \
|
||||||
|
-d $PLUTO_PEER_CLIENT $D_PEER_PORT -j ACCEPT
|
||||||
|
iptables -D FORWARD -i $TUN_NAME -p $PLUTO_MY_PROTOCOL \
|
||||||
|
-s $PLUTO_PEER_CLIENT $S_PEER_PORT \
|
||||||
|
-d $PLUTO_MY_CLIENT $D_MY_PORT -j ACCEPT
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
moon::swanctl --terminate --ike gw-gw 2> /dev/null
|
||||||
|
moon::systemctl stop strongswan
|
||||||
|
sun::systemctl stop strongswan
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
|
moon::systemctl start strongswan
|
||||||
|
sun::systemctl start strongswan
|
||||||
|
moon::expect-connection gw-gw
|
||||||
|
sun::expect-connection gw-gw
|
||||||
|
moon::swanctl --initiate --child net-net 2> /dev/null
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="alice moon winnetou sun bob"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="a-m-w-s-b.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
|
|
||||||
|
# charon controlled by swanctl
|
||||||
|
#
|
||||||
|
SWANCTL=1
|
||||||
Reference in New Issue
Block a user