An article explaining how to independently verify that your IPSec

configuration is working.
This commit is contained in:
Nik Clayton 2000-06-26 09:10:24 +00:00
parent 2ee393d1be
commit 3a76b7c251
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=7457
4 changed files with 626 additions and 0 deletions

View file

@ -0,0 +1,16 @@
# $FreeBSD$
DOC?= article
DOCFORMAT= html
FORMATS?= html
INSTALL_COMPRESSED?=gz
INSTALL_ONLY_COMPRESSED?=
SRCS= article.sgml
DOC_PREFIX?= ${.CURDIR}/../../..
.include "${DOC_PREFIX}/share/mk/doc.project.mk"

View file

@ -0,0 +1,297 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Independent Verification of IPSec Functionality in FreeBSD</title>
</head>
<body text="#000000" bgcolor="#FFFFFF">
<h1>Independent Verification of IPsec Functionality Under FreeBSD 3.0</h1>
<p align="center"><i>You installed IPsec and it seems to be working.&nbsp;
How do you know? I describe a method for experimentally verifying
that IPsec is working</i></p>
<h2>The Problem</h2>
<p>First, let's assume you have <a href="#Installing IPsec">installed
<i>IPsec</i></a>. How do you know its <a href="#Caveat">working</a>?
Sure, your connection won't work if its misconfigured, and it will work
when you finally get it right. <i>Netstat</i> will list it. But can you
independently confirm it?</p>
<h2>The Solution</h2>
<p>First, some crypto-relevent info theory:</p>
<ol>
<li>
<p>Encrypted data is uniformly distributed, ie, has maximal entropy
per symbol.</p>
</li>
<li>
<p>Raw, uncompressed data is typically redundant, i.e., has
sub-maximal entropy.</p>
</li>
</ol>
<p>Suppose you could measure the entropy of the data to- and from- your
network interface. Then you could see the difference between unencrypted
data and encrypted data. This would be true even if some of the data
in "encrypted mode" was not encrypted ---as the outermost IP header must
be, if the packet is to be routable.</p>
<h4><a name="MUST"></a>MUST</h4>
<p>Ueli Maurer's "Universal Statistical Test for Random Bit Generators"
("MUST") quickly measures the entropy of a sample. It uses a
compression-like algorithm. <a href="#Maurer's Universal Statistical
Test">The code is given below for a variant which measures successive
(~quarter megabyte) chunks of a file</a>.</p>
<h4><a NAME="Tcpdump"></a>Tcpdump</h4>
<p>We also need a way to capture the raw network data. A program called
"<i>tcpdump</i>" lets you do this, if you have enabled the <i>Berkeley
Packet Filter</i> interface in your <a
href="#usr/src/sys/i386/conf/KERNELNAME">kernel's config file</a>.</p>
<p>The command</p>
<blockquote><b>tcpdump</b> <b>-c</b> 4000 <b>-s</b> 10000 <b>-w</b>
<i>dumpfile.bin</i></blockquote>
<p>will capture 4000 raw packets to <i>dumpfile.bin</i>. Up to 10,000
bytes per packet will be captured in this example.</p>
<h2>The Experiment</h2>
<p>Here's the experiment. Open a window to an IPsec host and another
window to an insecure host.</p>
<p>Now start <a href="#Tcpdump">capturing packets</a>.</p>
<p>In the "secure" window, run the unix command "yes", which will stream
the "y" character. After a while, stop this. Switch to the insecure
window, and repeat. After a while, stop.</p>
<p>Now run <a href="#Maurer's Universal Statistical Test">MUST</a> on the
captured packets. You should see something like the the following.
The important thing to note is that the secure connection has 93% (6.7)
of the expected value (7.18), and the "normal" connection has 29% (2.1)
of the expected value.</p>
<pre>% tcpdump -c 4000 -s 10000 -w ipsecdemo.bin
% uliscan ipsecdemo.bin
Uliscan 21 Dec 98
L=8 256 258560
Measuring file ipsecdemo.bin
Init done
Expected value for L=8 is 7.1836656
6.9396 --------------------------------------------------------
6.6177 -----------------------------------------------------
6.4100 ---------------------------------------------------
2.1101 -----------------
2.0838 -----------------
2.0983 -----------------</pre>
<h2><a NAME="Caveat"></a>Caveat</h2>
<p>This experiment shows that IPsec <i>does</i> seem to be distributing the
payload data <i>uniformly</i>, as encryption should. However, the
experiment described here <i>can not </i>detect many possible flaws in a
system (none of which do I have any evidence for). These include poor
key generation or exchange, data or keys being visible to others, use of
weak algorithms, kernel subversion, etc. Study the source; know the
code.</p>
<h2><a NAME="IPsec"></a>IPsec -Definition</h2>
<p>Internet Protocol security extensions to IP v 4; required for IP v6. A
protocol for negotiating encryption and authentication at the IP
(host-to-host) level. SSL secures only one application socket; SSH
secures only a login; PGP secures only a specified file or
message. IPsec encrypts everything between two hosts.</p>
<h2><a NAME="Installing IPsec"></a>Installing IPsec</h2>
<p>Starting from the BSD 3.0 stable release,</p>
<ol>
<li>
<p>install IPsec v0.04, rebuild, reinstall</p>
</li>
<li>
<p>run the administration tools (e.g, <i>ipsecadm</i>) and distribute
keys (or use <i>Photuris</i> for key exchange)</p>
</li>
<li>
<p>set the routes (<i>rt</i>) up appropriately</p>
</li>
</ol>
<p>You may want to make an "ipsec_setup" script containing the
<i>ipsecadm</i> and <i>rt</i> commands which establish your IPsec
tunnel. You can run this script automatically at boottime from your
<i>/etc/rc.local</i> The ipsec_setup script will have to contain at
least two <i>ipsecadm</i> commands and one <i>rt</i> command to be
useful.</p>
<h2><a NAME="KERNELNAME"></a>usr/src/sys/i386/conf/KERNELNAME</h2>
<p>This needs to be present in the kernel config file in order to run
IPsec. After adding it, run <i>config</i>, etc. and rebuild and
reinstall.</p>
<pre># The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be
# aware of the legal and administrative consequences of enabling this
# option. Heh heh. The number of devices determines the maximum number of
# simultaneous BPF clients programs runnable.
pseudo-device bpfilter 2 #Berkeley packet filter
# IPSEC
options IPSEC
options "MD5"
pseudo-device enc 1</pre>
<h2><a name="must"></a>Maurer's Universal Statistical Test (for block
size=8 bits)</h2>
<pre><![ CDATA [/*
ULISCAN.c ---blocksize of 8
1 Oct 98
1 Dec 98
21 Dec 98 uliscan.c derived from ueli8.c
This version has // comments removed for Sun cc
This implements Ueli M Maurer's "Universal Statistical Test for Random
Bit Generators" using L=8
Accepts a filename on the command line; writes its results, with other
info, to stdout.
Handles input file exhaustion gracefully.
Ref: J. Cryptology v 5 no 2, 1992 pp 89-105
also on the web somewhere, which is where I found it.
-David Honig
honig@sprynet.com
Usage:
ULISCAN filename
outputs to stdout
*/
#define L 8
#define V (1<<L)
#define Q (10*V)
#define K (100 *Q)
#define MAXSAMP (Q + K)
#include <stdio.h>
#include <math.h>
int main(argc, argv)
int argc;
char **argv;
{
FILE *fptr;
int i,j;
int b, c;
int table[V];
double sum = 0.0;
int iproduct = 1;
int run;
extern double log(/* double x */);
printf("Uliscan 21 Dec 98 \nL=%d %d %d \n", L, V, MAXSAMP);
if (argc < 2) {
printf("Usage: Uliscan filename\n");
exit(-1);
} else {
printf("Measuring file %s\n", argv[1]);
}
fptr = fopen(argv[1],"rb");
if (fptr == NULL) {
printf("Can't find %s\n", argv[1]);
exit(-1);
}
for (i = 0; i < V; i++) {
table[i] = 0;
}
for (i = 0; i < Q; i++) {
b = fgetc(fptr);
table[b] = i;
}
printf("Init done\n");
printf("Expected value for L=8 is 7.1836656\n");
run = 1;
while (run) {
sum = 0.0;
iproduct = 1;
if (run)
for (i = Q; run && i < Q + K; i++) {
j = i;
b = fgetc(fptr);
if (b < 0)
run = 0;
if (run) {
if (table[b] > j)
j += K;
sum += log((double)(j-table[b]));
table[b] = i;
}
}
if (!run)
printf("Premature end of file; read %d blocks.\n", i - Q);
sum = (sum/((double)(i - Q))) / log(2.0);
printf("%4.4f ", sum);
for (i = 0; i < (int)(sum*8.0 + 0.50); i++)
printf("-");
printf("\n");
/* refill initial table */
if (0) {
for (i = 0; i < Q; i++) {
b = fgetc(fptr);
if (b < 0) {
run = 0;
} else {
table[b] = i;
}
}
}
}
}]]></pre>
</body>
</html>

View file

@ -0,0 +1,16 @@
# $FreeBSD$
DOC?= article
DOCFORMAT= html
FORMATS?= html
INSTALL_COMPRESSED?=gz
INSTALL_ONLY_COMPRESSED?=
SRCS= article.sgml
DOC_PREFIX?= ${.CURDIR}/../../..
.include "${DOC_PREFIX}/share/mk/doc.project.mk"

View file

@ -0,0 +1,297 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Independent Verification of IPSec Functionality in FreeBSD</title>
</head>
<body text="#000000" bgcolor="#FFFFFF">
<h1>Independent Verification of IPsec Functionality Under FreeBSD 3.0</h1>
<p align="center"><i>You installed IPsec and it seems to be working.&nbsp;
How do you know? I describe a method for experimentally verifying
that IPsec is working</i></p>
<h2>The Problem</h2>
<p>First, let's assume you have <a href="#Installing IPsec">installed
<i>IPsec</i></a>. How do you know its <a href="#Caveat">working</a>?
Sure, your connection won't work if its misconfigured, and it will work
when you finally get it right. <i>Netstat</i> will list it. But can you
independently confirm it?</p>
<h2>The Solution</h2>
<p>First, some crypto-relevent info theory:</p>
<ol>
<li>
<p>Encrypted data is uniformly distributed, ie, has maximal entropy
per symbol.</p>
</li>
<li>
<p>Raw, uncompressed data is typically redundant, i.e., has
sub-maximal entropy.</p>
</li>
</ol>
<p>Suppose you could measure the entropy of the data to- and from- your
network interface. Then you could see the difference between unencrypted
data and encrypted data. This would be true even if some of the data
in "encrypted mode" was not encrypted ---as the outermost IP header must
be, if the packet is to be routable.</p>
<h4><a name="MUST"></a>MUST</h4>
<p>Ueli Maurer's "Universal Statistical Test for Random Bit Generators"
("MUST") quickly measures the entropy of a sample. It uses a
compression-like algorithm. <a href="#Maurer's Universal Statistical
Test">The code is given below for a variant which measures successive
(~quarter megabyte) chunks of a file</a>.</p>
<h4><a NAME="Tcpdump"></a>Tcpdump</h4>
<p>We also need a way to capture the raw network data. A program called
"<i>tcpdump</i>" lets you do this, if you have enabled the <i>Berkeley
Packet Filter</i> interface in your <a
href="#usr/src/sys/i386/conf/KERNELNAME">kernel's config file</a>.</p>
<p>The command</p>
<blockquote><b>tcpdump</b> <b>-c</b> 4000 <b>-s</b> 10000 <b>-w</b>
<i>dumpfile.bin</i></blockquote>
<p>will capture 4000 raw packets to <i>dumpfile.bin</i>. Up to 10,000
bytes per packet will be captured in this example.</p>
<h2>The Experiment</h2>
<p>Here's the experiment. Open a window to an IPsec host and another
window to an insecure host.</p>
<p>Now start <a href="#Tcpdump">capturing packets</a>.</p>
<p>In the "secure" window, run the unix command "yes", which will stream
the "y" character. After a while, stop this. Switch to the insecure
window, and repeat. After a while, stop.</p>
<p>Now run <a href="#Maurer's Universal Statistical Test">MUST</a> on the
captured packets. You should see something like the the following.
The important thing to note is that the secure connection has 93% (6.7)
of the expected value (7.18), and the "normal" connection has 29% (2.1)
of the expected value.</p>
<pre>% tcpdump -c 4000 -s 10000 -w ipsecdemo.bin
% uliscan ipsecdemo.bin
Uliscan 21 Dec 98
L=8 256 258560
Measuring file ipsecdemo.bin
Init done
Expected value for L=8 is 7.1836656
6.9396 --------------------------------------------------------
6.6177 -----------------------------------------------------
6.4100 ---------------------------------------------------
2.1101 -----------------
2.0838 -----------------
2.0983 -----------------</pre>
<h2><a NAME="Caveat"></a>Caveat</h2>
<p>This experiment shows that IPsec <i>does</i> seem to be distributing the
payload data <i>uniformly</i>, as encryption should. However, the
experiment described here <i>can not </i>detect many possible flaws in a
system (none of which do I have any evidence for). These include poor
key generation or exchange, data or keys being visible to others, use of
weak algorithms, kernel subversion, etc. Study the source; know the
code.</p>
<h2><a NAME="IPsec"></a>IPsec -Definition</h2>
<p>Internet Protocol security extensions to IP v 4; required for IP v6. A
protocol for negotiating encryption and authentication at the IP
(host-to-host) level. SSL secures only one application socket; SSH
secures only a login; PGP secures only a specified file or
message. IPsec encrypts everything between two hosts.</p>
<h2><a NAME="Installing IPsec"></a>Installing IPsec</h2>
<p>Starting from the BSD 3.0 stable release,</p>
<ol>
<li>
<p>install IPsec v0.04, rebuild, reinstall</p>
</li>
<li>
<p>run the administration tools (e.g, <i>ipsecadm</i>) and distribute
keys (or use <i>Photuris</i> for key exchange)</p>
</li>
<li>
<p>set the routes (<i>rt</i>) up appropriately</p>
</li>
</ol>
<p>You may want to make an "ipsec_setup" script containing the
<i>ipsecadm</i> and <i>rt</i> commands which establish your IPsec
tunnel. You can run this script automatically at boottime from your
<i>/etc/rc.local</i> The ipsec_setup script will have to contain at
least two <i>ipsecadm</i> commands and one <i>rt</i> command to be
useful.</p>
<h2><a NAME="KERNELNAME"></a>usr/src/sys/i386/conf/KERNELNAME</h2>
<p>This needs to be present in the kernel config file in order to run
IPsec. After adding it, run <i>config</i>, etc. and rebuild and
reinstall.</p>
<pre># The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be
# aware of the legal and administrative consequences of enabling this
# option. Heh heh. The number of devices determines the maximum number of
# simultaneous BPF clients programs runnable.
pseudo-device bpfilter 2 #Berkeley packet filter
# IPSEC
options IPSEC
options "MD5"
pseudo-device enc 1</pre>
<h2><a name="must"></a>Maurer's Universal Statistical Test (for block
size=8 bits)</h2>
<pre><![ CDATA [/*
ULISCAN.c ---blocksize of 8
1 Oct 98
1 Dec 98
21 Dec 98 uliscan.c derived from ueli8.c
This version has // comments removed for Sun cc
This implements Ueli M Maurer's "Universal Statistical Test for Random
Bit Generators" using L=8
Accepts a filename on the command line; writes its results, with other
info, to stdout.
Handles input file exhaustion gracefully.
Ref: J. Cryptology v 5 no 2, 1992 pp 89-105
also on the web somewhere, which is where I found it.
-David Honig
honig@sprynet.com
Usage:
ULISCAN filename
outputs to stdout
*/
#define L 8
#define V (1<<L)
#define Q (10*V)
#define K (100 *Q)
#define MAXSAMP (Q + K)
#include <stdio.h>
#include <math.h>
int main(argc, argv)
int argc;
char **argv;
{
FILE *fptr;
int i,j;
int b, c;
int table[V];
double sum = 0.0;
int iproduct = 1;
int run;
extern double log(/* double x */);
printf("Uliscan 21 Dec 98 \nL=%d %d %d \n", L, V, MAXSAMP);
if (argc < 2) {
printf("Usage: Uliscan filename\n");
exit(-1);
} else {
printf("Measuring file %s\n", argv[1]);
}
fptr = fopen(argv[1],"rb");
if (fptr == NULL) {
printf("Can't find %s\n", argv[1]);
exit(-1);
}
for (i = 0; i < V; i++) {
table[i] = 0;
}
for (i = 0; i < Q; i++) {
b = fgetc(fptr);
table[b] = i;
}
printf("Init done\n");
printf("Expected value for L=8 is 7.1836656\n");
run = 1;
while (run) {
sum = 0.0;
iproduct = 1;
if (run)
for (i = Q; run && i < Q + K; i++) {
j = i;
b = fgetc(fptr);
if (b < 0)
run = 0;
if (run) {
if (table[b] > j)
j += K;
sum += log((double)(j-table[b]));
table[b] = i;
}
}
if (!run)
printf("Premature end of file; read %d blocks.\n", i - Q);
sum = (sum/((double)(i - Q))) / log(2.0);
printf("%4.4f ", sum);
for (i = 0; i < (int)(sum*8.0 + 0.50); i++)
printf("-");
printf("\n");
/* refill initial table */
if (0) {
for (i = 0; i < Q; i++) {
b = fgetc(fptr);
if (b < 0) {
run = 0;
} else {
table[b] = i;
}
}
}
}
}]]></pre>
</body>
</html>