aboutsummaryrefslogtreecommitdiff
path: root/rcynic/README
blob: 701c93a6c905ad9fdd8af08948d0adba200441c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
-*- Text -*- $Id$

"Cynical rsync" -- fetch and validate RPKI certificates.

To build this you will need to link it against an OpenSSL libcrypto
that has support for the RFC 3779 extensions.  See ../openssl/README.
 
I developed this code on FreeBSD 6-STABLE.  It is also known to run
work on Ubuntu (8.10) and Mac OS X (Snow Leopard).  In theory it
should run on any reasonably POSIX-like system.  As far as I know I
have not used any seriously non-portable features, but neither have I
done a POSIX reference manual lookup for every function call.  Please
report any portability problems.

All certificates and CRLs are in DER format, with filenames derived
from the RPKI rsync URIs at which the data are published.  See
../utils/ and ../rtr-origin/ for tools that use rcynic's output.

All configuration is via an OpenSSL-style configuration file, except
for selection of the name of the configuration file itself.  A few of
the parameters can also be set from the command line, to simplify
testing.  The default name for the configuration is rcynic.conf; you
can override this with the -c option on the command line.  The config
file uses OpenSSL's config file syntax, and you can set OpenSSL
library configuration paramaters (eg, "engine" settings) in the config
file as well.  rcynic's own configuration parameters are in a section
called "[rcynic]".

Most configuration parameters are optional and have defaults that
should do something reasonable if you are running rcynic in a test
directory.  If you're running it as a system progran, perhaps under
cron, you'll want to set additional parameters to tell rcynic where to
find its data and where to write its output.

The one thing you MUST specify in the config file in order for the
program to do anything useful is file name of one or more trust
anchors.  Trust anchors for this program are represented as
DER-formated X509 objects that look just like certificates, except
that they're trust anchors.

Strictly speaking, trust anchors do not need to be self-signed, but
many programs (including OpenSSL ) assume that trust anchors will be
self-signed.  See the allow-non-self-signed-trust-anchor configuration
option if you need to use a non-self-signed trust anchor, but be
warned that the results, while technically correct, may not be useful.

There are two ways of specifying trust anchors:

- Via the "trust-anchor" directive, to name a local file containing
  the DER-encoded trust anchor.

- Via the "trust-anchor-locator" directive, to name a local file
  containing a "trust anchor locator" (TAL).  See draft-ietf-sidr-ta
  for details [update this once RFC has been issued].

In most cases, except perhaps for testing, you will want to use trust
anchor locators, since they allow the trust anchor itself to be
updated without requiring reconfiguration of rcynic.

See the make-tal.sh script in this directory if you need to generate
your own TAL file for a trust anchor.

As of when I write this documentation, there still is no global trust
anchor for the RPKI system, so you have to specify separate trust
anchors for each RIR that's publishing data:

Example of a minimal config file:

    [rcynic]

    trust-anchor-locator.0 = trust-anchors/apnic.tal
    trust-anchor-locator.1 = trust-anchors/ripe.tal
    trust-anchor-locator.2 = trust-anchors/afrinic.tal
    trust-anchor-locator.3 = trust-anchors/lacnic.tal
    
Eventually, this should all be collapsed into a single trust anchor,
so that relying parties (people running tools like rcynic) don't need
to sort out this sort of issue, at which point the above
configuration can become something like:

    [rcynic]

    trust-anchor-locator = trust-anchors/iana.tal


By default, rcynic uses two writable directory trees:

- unauthenticated	Raw data fetched via rsync.  In order to take
			full advantage of rsync's optimized transfers,
			you should preserve and reuse this directory
			across rcynic runs, so that rcynic need not
			re-fetch data that have not changed.

- authenticated		Data that rcynic has checked.  This is the
			real output of the process.

authenticated is really a symbolic link to a directory with a name of
the form authenticated.<timestamp>, where <timestamp> is an ISO 8601
timestamp like 2001-04-01T01:23:45Z.  rcynic creates a new timestamped
directory every time it runs, and moves the symbolic link as an atomic
operation when the validation process completes.  The intent is that
authenticated always points to the most recent usable validation
results, so that programs which use rcynic's output don't need to
worry about whether an rcynic run is in progress.

rynic stores trust anchors specified via the trust-anchor-locator
directive in the unauthenticated tree just like any other fetched
object, and copies into the authenticated trees just like any other
object once they pass rcynic's checks.

rcynic copies trust anchors specified via the "trust-anchor" directive
into the top level directory of the authenticated tree xxxxxxxx.n.cer,
where xxxxxxxx and n are the OpenSSL object name hash and index within
the resulting virtual hash bucket (the same as the c_hash Perl script
that comes with OpenSSL would produce), and ".cer" is the literal
string ".cer".  The reason for this is that these trust anchors, by
definition, are not fetched automatically, and thus do not really have
publication URIs in the sense that every other object in these trees
do.  So rcynic uses a naming scheme which insures (a) that each trust
anchor has a unique name within the output tree and (b) that trust
anchors cannot be confusd with certificates: trust anchors always go
in the top level of the tree, data fetched via rsync always go in
subdirectories.

As currently implemented, rcynic does not attempt to maintain an
in-memory cache of objects it might need again later.  It does keep an
internal cache of the URIs from which it has already fetched data in
this pass, and it keeps a stack containing the current certificate
chain as it does its validation walk.  All other data (eg, CRLs) are
freed immediately after use and read from disk again as needed.  From
a database design standpoint, this is not very efficient, but as the
rcynic's main bottlenecks are expected to be crypto and network
operations, it seemed best to keep the design as simple as possible,
at least until execution profiling demonstrates a real issue here.

Usage and configuration:

Logging levels:

rcynic has its own system of logging levels, similar to what syslog()
uses but customized to the specific task rcynic performs.  Levels:

 log_sys_err		Error from operating system or library
 log_usage_err		Bad usage (local configuration error)
 log_data_err		Bad data (broken certificates or CRLs)
 log_telemetry		Normal chatter about rcynic's progress
 log_verbose		Extra verbose chatter
 log_debug		Only useful when debugging

Command line options:

 -c configfile	Path to configuration file (default: rcynic.conf)
 -l loglevel	Logging level (default: log_data_err)
 -s		Log via syslog
 -e		Log via stderr when also using syslog
 -j		Start-up jitter interval (see below; default: 600)
 -V		Print rcynic's version to standard output and exit

Configuration file:

rcynic uses the OpenSSL libcrypto configuration file mechanism.  All
libcrypto configuration options (eg, for engine support) are
available.  All rcynic-specific options are in the "[rcynic]"
section.  You -must- have a configuration file in order for rcynic to
do anything useful, as the configuration file is the only way to list
your trust anchors.

Configuration variables:

authenticated		Path to output directory (where rcynic should
			place objects it has been able to validate).

			Default: rcynic-data/authenticated


unauthenticated		Path to directory where rcynic should store
			unauthenticatd data retrieved via rsync.
			Unless something goes horribly wrong, you want
			rcynic to preserve and reuse this directory
			across runs to minimize the network traffic
			necessary to bring your repository mirror up
			to date.

			Default: rcynic-data/unauthenticated


rsync-timeout		How long (in seconds) to let rsync run before
			terminating the rsync process, or zero for no
			timeout.  You want this timeout to be fairly
			long, to avoid terminating rsync connections
			prematurely.  It's present to let you defend
			against evil rsync server operators who try to
			tarpit your connection as a form of denial of
			service attack on rcynic.

			Default: 300 seconds.


max-parallel-fetches	Upper limit on the number of copies of rsync
			that rcynic is allowed to run at once.  Used
			properly, this can speed up synchronization
			considerably when fetching from repositories
			built with sub-optimal tree layouts or when
			dealing with unreachable repositories.  Used
			improperly, this option can generate excessive
			load on repositories, cause synchronization to
			be interrupted by firewalls, and generally
			creates create a public nuisance.  Use with
			caution.

			As of this writing, values in the range 2-4
			are reasonably safe.  At least one RIR
			currently refuses service at settings above 4,
			and another RIR appears to be running some
			kind of firewall that silently blocks
			connections when it thinks decides that the
			connection rate is excessive.

			rcynic can't really detect all of the possible
			problems created by excessive values of this
			parameter, but if rcynic's report shows that
			both successful retrivial and skipped
			retrieval from the same repository host,
			that's a pretty good hint that something is
			wrong, and an excessive value here is a good
			first guess as to the cause.

			Default: 1


rsync-program		Path to the rsync program.

			Default: rsync, but you should probably set
			this variable rather than just trusting the
			PATH environment variable to be set correctly.


log-level		Same as -l option on command line.  Command
			line setting overrides config file setting.

			Default: log_log_err


use-syslog		Same as -s option on command line.  Command
			line setting overrides config file setting.

			Values: true or false.

			Default: false


use-stderr		Same as -e option on command line.  Command
			line setting overrides config file setting.

			Values: true or false.

			Default: false, but if neither use-syslog nor
			use-stderr is set, log output goes to stderr.


syslog-facility		Syslog facility to use.

			Default: local0



syslog-priority-xyz	(where xyz is an rcynic logging level, above)
			Override the syslog priority value to use when
			logging messages at this rcynic level.

			Defaults:

			syslog-priority-log_sys_err:	err
			syslog-priority-log_usage_err:	err
			syslog-priority-log_data_err:	notice
			syslog-priority-log_telemetry:	info
			syslog-priority-log_verbose:	info
			syslog-priority-log_debug:	debug


jitter			Startup jitter interval, same as -j option on
			command line.  Jitter interval, specified in
			number of seconds.  rcynic will pick a random
			number within the interval from zero to this
			value, and will delay for that many seconds on
			startup.  The purpose of this is to spread the
			load from large numbers of rcynic clients all
			running under cron with synchronized clocks,
			in particular to avoid hammering the RPKI
			rsync servers into the ground at midnight UTC.

			Default: 600


lockfile		Name of lockfile, or empty for no lock.  If
			you run rcynic under cron, you should use this
			parameter to set a lockfile so that successive
			instances of rcynic don't stomp on each other.

			Default: no lock

xml-summary		Enable output of a per-host summary at the
			end of an rcynic run in XML format.  Some
			users prefer this to the log_telemetry style
			of logging, or just want it in addition to
			logging.  Value: filename to which XML summary
			should be written; "-" will send XML summary
			to stdout.

			Default: no XML summary


allow-stale-crl		Allow use of CRLs which are past their
			nextUpdate timestamp.  This is probably
			harmless, but since it may be an early warning
			of problems, it's configurable.

			Values: true or false.

			Default: true


prune			Clean up old files corresponding to URIs that
			rcynic did not see at all during this run.
			rcynic invokes rsync with the --delete option
			to clean up old objects from collections that
			rcynic revisits, but if a URI changes so that
			rcynic never visits the old collection again,
			old files will remain in the local mirror
			indefinitely unless you enable this option.

			Note: Pruning only happens when run-rsync is
			true.  When the run-rsync option is false,
			pruning is not done regardless of the setting
			of the prune option option.

			Values: true or false.

			Default: true


allow-stale-manifest	Allow use of manifests which are past their
			nextUpdate timestamp.  This is probably
			harmless, but since it may be an early warning
			of problems, it's configurable.

			Values: true or false.

			Default: true


require-crl-in-manifest	Reject publication point if manifest doesn't
			list the CRL that covers the manifest EE
			certificate.

			Values: true or false.

			Default: false


allow-object-not-in-manifest
			Allow use of otherwise valid objects which are
			not listed in the manifest.  This is not
			supposed to happen, but is probably harmless.

			Values: true or false

			Default: true


allow-digest-mismatch
			Allow use of otherwise valid objects which are
			listed in the manifest with a different digest
			value.

			You probably don't want to touch this.

			Values: true or false

			Default: true


allow-crl-digest-mismatch
			Allow processing to continue on a publication
			point whose manifest lists a different digest
			value for the CRL than the digest of the CRL
			we have in hand.

			You probably don't want to touch this.

			Values: true or false

			Default: true


allow-non-self-signed-trust-anchor
			Experimental.  Attempts to work around OpenSSL's
			strong preference for self-signed trust
			anchors.  Do not use this unless you really know
			what you are doing.

			Values: true or false.

			Default: false


run-rsync

			Whether to run rsync to fetch data.  You don't
			want to change this except when building
			complex topologies where rcynic running on one
			set of machines acts as aggregators for
			another set of validators.  A large ISP might
			want to build such a topology so that they
			could have a local validation cache in each
			POP while minimizing load on the global
			repository system and maintaining some degree
			of internal consistancy between POPs.  In such
			cases, one might want the rcynic instances in
			the POPs to validate data fetched from the
			aggregators via an external process, without
			the POP rcynic instances attempting to fetch
			anything themselves.

			Don't touch this unless you really know what
			you're doing.

			Values: true or false.

			Default: true


use-links		Whether to use hard links rather than copying
			valid objects from the unauthenticated to
			authenticated tree.  Using links is slightly
			more fragile (anything that stomps on the
			unauthenticated file also stomps on the
			authenticated file) but is a bit faster and
			reduces the number of inodes consumed by a
			large data collection.  At the moment, copying
			is the default behavior, but this may change
			in the future.

			Values: true or false.

			Default: false


trust-anchor		Specify one RPKI trust anchor, represented as
			a local file containing an X.509 certificate
			in DER format.  Value of this option is the
			pathname of the file.

			No default.


trust-anchor-locator
			Specify one RPKI trust anchor, represented as
			a local file containing an rsync URI and the
			RSA public key of the X.509 object specified
			by the URI.  First line of the file is the
			URI, remainder is the public key in Base64
			encoded DER format.  Value of this option
			is the pathname of the file.

			No default.


There's a companion XSLT template in rcynic.xsl, which translates what
the xml-summary option writes into HTML.



Running rcynic chrooted

This is an attempt to describe the process of setting up rcynic in a
chrooted environment.  The installation scripts that ship with rcynic
attempt to do this automatically for the platforms we support, but the
process is somewhat finicky, so some explanation seems in order.  If
you're running on one of the supported platforms, the following steps
may be handled for you by the Makefiles, but you may still want to
understand what all this is trying to do.

rcynic itself does not include any direct support for running
chrooted, but is designed to be (relatively) easy to run in a chroot
jail.  Here's how.

You'll either need staticly linked copies of rcynic and rsync, or
you'll need to figure out which shared libraries these programs need
(try using the "ldd" command).  Here we assume staticly linked
binaries, because that's simpler.

You'll need a chroot wrapper program.  Your platform may already have
one (FreeBSD does -- /usr/sbin/chroot), but if you don't, you can
download Wietse Venema's "chrootuid" program from:

  ftp://ftp.porcupine.org/pub/security/chrootuid1.3.tar.gz

Warning: The chroot program included in at least some Linux
distributions is not adaquate to this task, you need a wrapper that
knows how to drop privileges after performing the chroot() operation
itself.  If in doubt, use chrootuid.

Unfortunately, the precise details of setting up a proper chroot jail
vary wildly from one system to another, so the following instructions
will likely not be a precise match for the preferred way of doing this
on any particular platform.  We have sample scripts that do the right
thing for FreeBSD, feel free to contribute such scripts for other
platforms.

Step 1: Build the static binaries.  You might want to test them at
this stage too, although you can defer that until after you've got the
jail built.

Step 2: Create a userid under which to run rcynic.  Here we'll assume
that you've created a user "rcynic", whose default group is also named
"rcynic".  Do not add any other userids to the rcynic group unless you
really know what you are doing.

Step 3: Build the jail.  You'll need, at minimum, a directory in which
to put the binaries, a subdirectory tree that's writable by the userid
which will be running rcynic and rsync, your trust anchors, and
whatever device inodes the various libraries need on your system.
Most likely the devices that matter will be /dev/null, /dev/random,a
nd /dev/urandom; if you're running a FreeBSD system with devfs, you
do this by mounting and configuring a devfs instance in the jail, on
other platforms you probably use the mknod program or something.

Important: other than the directories that you want rcynic and rsync
to be able to modify, -nothing- in the initial jail setup should be
writable by the rcynic userid.  In particular, rcynic and rsync should
-not- be allowed to modify: their own binary images, any of the
configuration files, or your trust anchors.  It's simplest just to
have root own all the files and directories that rcynic and rsync are
not allowed to modify, and make sure that the permissions for all of
those directories and files make them writable only by root.

Sample jail tree, assuming that we're putting all of this under
/var/rcynic:

 # mkdir /var/rcynic
 # mkdir /var/rcynic/bin
 # mkdir /var/rcynic/data
 # mkdir /var/rcynic/dev
 # mkdir /var/rcynic/etc
 # mkdir /var/rcynic/etc/trust-anchors

Copy your trust anchors into /var/rcynic/etc/trust-anchors.

Copy the staticly linked rcynic and rsync into /var/rcynic/bin.

Copy /etc/resolv.conf and /etc/localtime (if it exists) into
/var/rcynic/etc.

Write an rcynic configuration file as /var/rcynic/etc/rcynic.conf
(path names in this file must match the jail setup, more below).

 # chmod -R go-w /var/rcynic
 # chown -R root:wheel /var/rcynic
 # chown -R rcynic:rcynic /var/rcynic/data

If you're using devfs, arrange for it to be mounted at
/var/rcynic/dev; otherwise, create whatever device inodes you need in
/var/rcynic/dev and make sure that they have sane permissions (copying
whatever permissions are used in your system /dev directory should
suffice).

rcynic.conf to match this configuration:

  [rcynic]

  trust-anchor-locator.1	= /etc/trust-anchors/ta-1.tal
  trust-anchor-locator.2	= /etc/trust-anchors/ta-2.tal
  trust-anchor-locator.3	= /etc/trust-anchors/ta-3.tal

  rsync-program			= /bin/rsync
  authenticated			= /data/authenticated
  unauthenticated		= /data/unauthenticated

Once you've got all this set up, you're ready to try running rcynic in
the jail.  Try it from the command line first, then if that works, you
should be able to run it under cron.

Note: chroot, chrootuid, and other programs of this type are usually
intended to be run by root, and should -not- be setuid programs unless
you -really- know what you are doing.

Sample command line:

  # /usr/local/bin/chrootuid /var/rcynic rcynic /bin/rcynic -s -c /etc/rcynic.conf

Note that we use absolute pathnames everywhere.  This is not an
accident.  Programs running in jails under cron should not make
assumptions about the current working directory or environment
variable settings, and programs running in chroot jails would need
different PATH settings anyway.  Best just to specify everything.

Building static binaries:

On FreeBSD, building a staticly linked rsync is easy: just set the
environment variable LDFLAGS='-static' before building the rsync port
and the right thing will happen.  Since this is really just GNU
configure picking up the environment variable, the same trick should
work on other platforms...except that some compilers don't support
-static, and some platforms are missing some or all of the non-shared
libraries you'd need to link the resulting binary.

For simplicity, I've taken the same approach with rcynic, so 

  $ make LDFLAGS='-static'

should work.  Except that you don't even have to do that: static
linking is the default where supported, because I run it jailed.

syslog:

Depending on your syslogd configuration, syslog may not work properly
with rcynic in a chroot jail.  On FreeBSD, the easiest way to fix this
is to add the following lines to /etc/rc.conf:

    altlog_proglist="named rcynic"
    rcynic_chrootdir="/var/rcynic"
    rcynic_enable="YES"