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:
commit
e3cb756dbf
58 files changed
+1382
-82
No files matched your search
@@ -5,3 +5,10 @@ charon.plugins.kernel-libipsec.allow_peer_ts = no
|
||||
installed for such traffic (via TUN device) usually prevents further IKE
|
||||
traffic. The fwmark options for the _kernel-netlink_ and _socket-default_
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Outbound callback
|
||||
*/
|
||||
static void send_esp(void *data, esp_packet_t *packet)
|
||||
CALLBACK(send_esp, void,
|
||||
void *data, esp_packet_t *packet, bool encap)
|
||||
{
|
||||
charon->sender->send_no_marker(charon->sender, (packet_t*)packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inbound callback
|
||||
*/
|
||||
static void deliver_plain(private_android_service_t *this,
|
||||
ip_packet_t *packet)
|
||||
CALLBACK(deliver_plain, void,
|
||||
private_android_service_t *this, ip_packet_t *packet)
|
||||
{
|
||||
chunk_t encoding;
|
||||
ssize_t len;
|
||||
@@ -122,10 +117,8 @@ static void deliver_plain(private_android_service_t *this,
|
||||
packet->destroy(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiver callback
|
||||
*/
|
||||
static void receiver_esp_cb(void *data, packet_t *packet)
|
||||
CALLBACK(receiver_esp_cb, void,
|
||||
void *data, packet_t *packet)
|
||||
{
|
||||
esp_packet_t *esp_packet;
|
||||
|
||||
@@ -359,14 +352,10 @@ static bool setup_tun_device(private_android_service_t *this,
|
||||
|
||||
if (!already_registered)
|
||||
{
|
||||
charon->receiver->add_esp_cb(charon->receiver,
|
||||
(receiver_esp_cb_t)receiver_esp_cb, NULL);
|
||||
ipsec->processor->register_inbound(ipsec->processor,
|
||||
(ipsec_inbound_cb_t)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);
|
||||
charon->receiver->add_esp_cb(charon->receiver, receiver_esp_cb, NULL);
|
||||
ipsec->processor->register_inbound(ipsec->processor, deliver_plain, this);
|
||||
ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL);
|
||||
this->dns_proxy->register_cb(this->dns_proxy, deliver_plain, this);
|
||||
|
||||
lib->processor->queue_job(lib->processor,
|
||||
(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->lock->unlock(this->lock);
|
||||
|
||||
this->dns_proxy->unregister_cb(this->dns_proxy,
|
||||
(dns_proxy_response_cb_t)deliver_plain);
|
||||
ipsec->processor->unregister_outbound(ipsec->processor,
|
||||
(ipsec_outbound_cb_t)send_esp);
|
||||
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);
|
||||
this->dns_proxy->unregister_cb(this->dns_proxy, deliver_plain);
|
||||
ipsec->processor->unregister_outbound(ipsec->processor, send_esp);
|
||||
ipsec->processor->unregister_inbound(ipsec->processor, deliver_plain);
|
||||
charon->receiver->del_esp_cb(charon->receiver, receiver_esp_cb);
|
||||
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,
|
||||
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,
|
||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||
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,
|
||||
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,
|
||||
id->src, id->dst, data->new_src, data->new_dst, data->encap,
|
||||
data->new_encap, id->mark);
|
||||
|
||||
@@ -15,7 +15,8 @@ endif
|
||||
libstrongswan_kernel_libipsec_la_SOURCES = \
|
||||
kernel_libipsec_plugin.h kernel_libipsec_plugin.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
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
bool allow_peer_ts;
|
||||
|
||||
/**
|
||||
* Whether UDP encapsulation is required
|
||||
*/
|
||||
bool require_encap;
|
||||
};
|
||||
|
||||
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,
|
||||
private_kernel_libipsec_ipsec_t *this)
|
||||
{
|
||||
return KERNEL_REQUIRE_UDP_ENCAPSULATION | KERNEL_ESP_V3_TFC |
|
||||
KERNEL_SA_USE_TIME;
|
||||
return KERNEL_ESP_V3_TFC | KERNEL_SA_USE_TIME |
|
||||
(this->require_encap ? KERNEL_REQUIRE_UDP_ENCAPSULATION : 0);
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
data->reqid, id->mark, data->tfc, data->lifetime,
|
||||
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(),
|
||||
.allow_peer_ts = lib->settings->get_bool(lib->settings,
|
||||
"%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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Tobias Brunner
|
||||
* Copyright (C) 2012-2023 Tobias Brunner
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
*
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "kernel_libipsec_plugin.h"
|
||||
#include "kernel_libipsec_ipsec.h"
|
||||
#include "kernel_libipsec_router.h"
|
||||
#include "kernel_libipsec_esp_handler.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <ipsec.h>
|
||||
@@ -45,6 +46,11 @@ struct private_kernel_libipsec_plugin_t {
|
||||
* Packet router
|
||||
*/
|
||||
kernel_libipsec_router_t *router;
|
||||
|
||||
/**
|
||||
* Raw ESP handler
|
||||
*/
|
||||
kernel_libipsec_esp_handler_t *esp_handler;
|
||||
};
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
@@ -92,6 +98,11 @@ METHOD(plugin_t, destroy, void,
|
||||
lib->set(lib, "kernel-libipsec-tun", NULL);
|
||||
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();
|
||||
free(this);
|
||||
}
|
||||
@@ -146,5 +157,17 @@ plugin_t *kernel_libipsec_plugin_create()
|
||||
/* set TUN device as default to install VIPs */
|
||||
lib->settings->set_str(lib->settings, "%s.install_virtual_ip_on",
|
||||
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;
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "kernel_libipsec_router.h"
|
||||
#include "kernel_libipsec_esp_handler.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <ipsec.h>
|
||||
@@ -76,6 +77,11 @@ struct private_kernel_libipsec_router_t {
|
||||
* Pipe to signal handle_plain() about changes regarding TUN devices
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outbound callback
|
||||
*/
|
||||
static void send_esp(void *data, esp_packet_t *packet)
|
||||
CALLBACK(send_esp, void,
|
||||
private_kernel_libipsec_router_t *this, esp_packet_t *packet, bool encap)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiver callback
|
||||
*/
|
||||
static void receiver_esp_cb(void *data, packet_t *packet)
|
||||
CALLBACK(receiver_esp_cb, void,
|
||||
void *data, packet_t *packet)
|
||||
{
|
||||
ipsec->processor->queue_inbound(ipsec->processor,
|
||||
esp_packet_create_from_packet(packet));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inbound callback
|
||||
*/
|
||||
static void deliver_plain(private_kernel_libipsec_router_t *this,
|
||||
ip_packet_t *packet)
|
||||
CALLBACK(deliver_plain, void,
|
||||
private_kernel_libipsec_router_t *this, ip_packet_t *packet)
|
||||
{
|
||||
tun_device_t *tun;
|
||||
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,
|
||||
private_kernel_libipsec_router_t *this)
|
||||
{
|
||||
charon->receiver->del_esp_cb(charon->receiver,
|
||||
(receiver_esp_cb_t)receiver_esp_cb);
|
||||
ipsec->processor->unregister_outbound(ipsec->processor,
|
||||
(ipsec_outbound_cb_t)send_esp);
|
||||
ipsec->processor->unregister_inbound(ipsec->processor,
|
||||
(ipsec_inbound_cb_t)deliver_plain);
|
||||
charon->receiver->del_esp_cb(charon->receiver, receiver_esp_cb);
|
||||
ipsec->processor->unregister_outbound(ipsec->processor, send_esp);
|
||||
ipsec->processor->unregister_inbound(ipsec->processor, deliver_plain);
|
||||
charon->kernel->remove_listener(charon->kernel, &this->public.listener);
|
||||
this->lock->destroy(this->lock);
|
||||
this->tuns->destroy(this->tuns);
|
||||
@@ -333,7 +340,8 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
|
||||
},
|
||||
.tun = {
|
||||
.tun = lib->get(lib, "kernel-libipsec-tun"),
|
||||
}
|
||||
},
|
||||
.esp_handler = lib->get(lib, "kernel-libipsec-esp-handler"),
|
||||
);
|
||||
|
||||
if (pipe(this->notify) != 0 ||
|
||||
@@ -351,11 +359,9 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
|
||||
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
|
||||
|
||||
charon->kernel->add_listener(charon->kernel, &this->public.listener);
|
||||
ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL);
|
||||
ipsec->processor->register_inbound(ipsec->processor,
|
||||
(ipsec_inbound_cb_t)deliver_plain, this);
|
||||
charon->receiver->add_esp_cb(charon->receiver,
|
||||
(receiver_esp_cb_t)receiver_esp_cb, NULL);
|
||||
ipsec->processor->register_outbound(ipsec->processor, send_esp, this);
|
||||
ipsec->processor->register_inbound(ipsec->processor, deliver_plain, this);
|
||||
charon->receiver->add_esp_cb(charon->receiver, receiver_esp_cb, NULL);
|
||||
lib->processor->queue_job(lib->processor,
|
||||
(job_t*)callback_job_create((callback_job_cb_t)handle_plain, this,
|
||||
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
|
||||
*/
|
||||
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);
|
||||
if (this->outbound.cb)
|
||||
{
|
||||
this->outbound.cb(this->outbound.data, packet);
|
||||
this->outbound.cb(this->outbound.data, packet, encap);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -194,7 +194,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
||||
ip_packet_t *packet;
|
||||
ipsec_sa_t *sa;
|
||||
host_t *src, *dst;
|
||||
bool acquire = FALSE;
|
||||
bool acquire = FALSE, encap = FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
sa->update_usestats(sa, packet->get_encoding(packet).len);
|
||||
encap = sa->get_encap(sa);
|
||||
ipsec->sas->checkin(ipsec->sas, sa);
|
||||
policy->destroy(policy);
|
||||
send_outbound(this, esp_packet);
|
||||
send_outbound(this, esp_packet, encap);
|
||||
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
|
||||
*
|
||||
@@ -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 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
|
||||
|
||||
+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 Ralf Sager
|
||||
*
|
||||
@@ -69,6 +69,11 @@ struct private_ipsec_sa_t {
|
||||
*/
|
||||
ipsec_mode_t mode;
|
||||
|
||||
/**
|
||||
* TRUE if UDP encapsulation should be used when sending
|
||||
*/
|
||||
bool encap;
|
||||
|
||||
/**
|
||||
* TRUE if extended sequence numbers are used
|
||||
*/
|
||||
@@ -133,6 +138,18 @@ METHOD(ipsec_sa_t, set_destination, void,
|
||||
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,
|
||||
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");
|
||||
return NULL;
|
||||
}
|
||||
if (!encap)
|
||||
{
|
||||
DBG1(DBG_ESP, " IPsec SA: only UDP encapsulation is supported");
|
||||
return NULL;
|
||||
}
|
||||
if (esn)
|
||||
{
|
||||
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,
|
||||
.set_source = _set_source,
|
||||
.set_destination = _set_destination,
|
||||
.get_encap = _get_encap,
|
||||
.set_encap = _set_encap,
|
||||
.get_spi = _get_spi,
|
||||
.get_reqid = _get_reqid,
|
||||
.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,
|
||||
.reqid = reqid,
|
||||
.mode = mode,
|
||||
.encap = encap,
|
||||
.esn = esn,
|
||||
.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 Ralf Sager
|
||||
*
|
||||
@@ -66,6 +66,20 @@ struct ipsec_sa_t {
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
||||
@@ -502,7 +502,7 @@ METHOD(ipsec_sa_mgr_t, get_spi, 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,
|
||||
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,
|
||||
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,
|
||||
@@ -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",
|
||||
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);
|
||||
if (this->sas->find_first(this->sas, match_entry_by_spi_src_dst_cb,
|
||||
(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_destination(entry->sa, new_dst);
|
||||
entry->sa->set_encap(entry->sa, new_encap);
|
||||
/* checkin the entry */
|
||||
entry->locked = FALSE;
|
||||
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
|
||||
File renamed without changes.
+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
|
||||
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
|
||||
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::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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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