]> pere.pagekite.me Git - homepage.git/blob - blog/What_are_they_searching_for___PowerDNS_and_ISC_DHCP_in_LDAP.html
Generated.
[homepage.git] / blog / What_are_they_searching_for___PowerDNS_and_ISC_DHCP_in_LDAP.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html>
4 <head>
5 <title>Petter Reinholdtsen: What are they searching for - PowerDNS and ISC DHCP in LDAP</title>
6 <link rel="stylesheet" type="text/css" media="screen" href="http://people.skolelinux.org/pere/blog/style.css">
7 </head>
8 <body>
9
10 <div class="title">
11 <h1>
12 <a href="http://people.skolelinux.org/pere/blog/">Petter Reinholdtsen</a>
13
14 </h1>
15
16 </div>
17
18
19 <div class="entry">
20 <div class="title">What are they searching for - PowerDNS and ISC DHCP in LDAP</div>
21 <div class="date">2010-07-17 21:00</div>
22 <div class="body">
23 <p>This is a
24 <a href="http://people.skolelinux.org/pere/blog/Time_for_new__LDAP_schemas_replacing_RFC_2307_.html">followup</a>
25 on my
26 <a href="http://people.skolelinux.org/pere/blog/Idea_for_a_change_to_LDAP_schemas_allowing_DNS_and_DHCP_info_to_be_combined_into_one_object.html">previous
27 work</a> on
28 <a href="http://people.skolelinux.org/pere/blog/Combining_PowerDNS_and_ISC_DHCP_LDAP_objects.html">merging
29 all</a> the computer related LDAP objects in Debian Edu.</p>
30
31 <p>As a step to try to see if it possible to merge the DNS and DHCP
32 LDAP objects, I have had a look at how the packages pdns-backend-ldap
33 and dhcp3-server-ldap in Debian use the LDAP server. The two
34 implementations are quite different in how they use LDAP.</p>
35
36 To get this information, I started slapd with debugging enabled and
37 dumped the debug output to a file to get the LDAP searches performed
38 on a Debian Edu main-server. Here is a summary.
39
40 <p><strong>powerdns</strong></p>
41
42 <a href="http://www.linuxnetworks.de/doc/index.php/PowerDNS_LDAP_Backend">Clues
43 on how to</a> set up PowerDNS to use a LDAP backend is available on
44 the web.
45
46 <p>PowerDNS have two modes of operation using LDAP as its backend.
47 One "strict" mode where the forward and reverse DNS lookups are done
48 using the same LDAP objects, and a "tree" mode where the forward and
49 reverse entries are in two different subtrees in LDAP with a structure
50 based on the DNS names, as in tjener.intern and
51 2.2.0.10.in-addr.arpa.</p>
52
53 <p>In tree mode, the server is set up to use a LDAP subtree as its
54 base, and uses a "base" scoped search for the DNS name by adding
55 "dc=tjener,dc=intern," to the base with a filter for
56 "(associateddomain=tjener.intern)" for the forward entry and
57 "dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa," with a filter for
58 "(associateddomain=2.2.0.10.in-addr.arpa)" for the reverse entry. For
59 forward entries, it is looking for attributes named dnsttl, arecord,
60 nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord, mxrecord,
61 txtrecord, rprecord, afsdbrecord, keyrecord, aaaarecord, locrecord,
62 srvrecord, naptrrecord, kxrecord, certrecord, dsrecord, sshfprecord,
63 ipseckeyrecord, rrsigrecord, nsecrecord, dnskeyrecord, dhcidrecord,
64 spfrecord and modifytimestamp. For reverse entries it is looking for
65 the attributes dnsttl, arecord, nsrecord, cnamerecord, soarecord,
66 ptrrecord, hinforecord, mxrecord, txtrecord, rprecord, aaaarecord,
67 locrecord, srvrecord, naptrrecord and modifytimestamp. The equivalent
68 ldapsearch commands could look like this:</p>
69
70 <blockquote><pre>
71 ldapsearch -h ldap \
72 -b dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no \
73 -s base -x '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \
74 cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \
75 rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \
76 nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \
77 rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp
78
79 ldapsearch -h ldap \
80 -b dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no \
81 -s base -x '(associateddomain=2.2.0.10.in-addr.arpa)'
82 dnsttl, arecord, nsrecord, cnamerecord soarecord ptrrecord \
83 hinforecord mxrecord txtrecord rprecord aaaarecord locrecord \
84 srvrecord naptrrecord modifytimestamp
85 </pre></blockquote>
86
87 <p>In Debian Edu/Lenny, the PowerDNS tree mode is used with
88 ou=hosts,dc=skole,dc=skolelinux,dc=no as the base, and these are two
89 example LDAP objects used there. In addition to these objects, the
90 parent objects all th way up to ou=hosts,dc=skole,dc=skolelinux,dc=no
91 also exist.</p>
92
93 <blockquote><pre>
94 dn: dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no
95 objectclass: top
96 objectclass: dnsdomain
97 objectclass: domainrelatedobject
98 dc: tjener
99 arecord: 10.0.2.2
100 associateddomain: tjener.intern
101
102 dn: dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no
103 objectclass: top
104 objectclass: dnsdomain2
105 objectclass: domainrelatedobject
106 dc: 2
107 ptrrecord: tjener.intern
108 associateddomain: 2.2.0.10.in-addr.arpa
109 </pre></blockquote>
110
111 <p>In strict mode, the server behaves differently. When looking for
112 forward DNS entries, it is doing a "subtree" scoped search with the
113 same base as in the tree mode for a object with filter
114 "(associateddomain=tjener.intern)" and requests the attributes dnsttl,
115 arecord, nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord,
116 mxrecord, txtrecord, rprecord, aaaarecord, locrecord, srvrecord,
117 naptrrecord and modifytimestamp. For reverse entires it also do a
118 subtree scoped search but this time the filter is "(arecord=10.0.2.2)"
119 and the requested attributes are associateddomain, dnsttl and
120 modifytimestamp. In short, in strict mode the objects with ptrrecord
121 go away, and the arecord attribute in the forward object is used
122 instead.</p>
123
124 <p>The forward and reverse searches can be simulated using ldapsearch
125 like this:</p>
126
127 <blockquote><pre>
128 ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \
129 '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \
130 cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \
131 rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \
132 nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \
133 rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp
134
135 ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \
136 '(arecord=10.0.2.2)' associateddomain dnsttl modifytimestamp
137 </pre></blockquote>
138
139 <p>In addition to the forward and reverse searches , there is also a
140 search for SOA records, which behave similar to the forward and
141 reverse lookups.</p>
142
143 <p>A thing to note with the PowerDNS behaviour is that it do not
144 specify any objectclass names, and instead look for the attributes it
145 need to generate a DNS reply. This make it able to work with any
146 objectclass that provide the needed attributes.</p>
147
148 <p>The attributes are normally provided in the cosine (RFC 1274) and
149 dnsdomain2 schemas. The latter is used for reverse entries like
150 ptrrecord and recent DNS additions like aaaarecord and srvrecord.</p>
151
152 <p>In Debian Edu, we have created DNS objects using the object classes
153 dcobject (for dc), dnsdomain or dnsdomain2 (structural, for the DNS
154 attributes) and domainrelatedobject (for associatedDomain). The use
155 of structural object classes make it impossible to combine these
156 classes with the object classes used by DHCP.</p>
157
158 <p>There are other schemas that could be used too, for example the
159 dnszone structural object class used by Gosa and bind-sdb for the DNS
160 attributes combined with the domainrelatedobject object class, but in
161 this case some unused attributes would have to be included as well
162 (zonename and relativedomainname).</p>
163
164 <p>My proposal for Debian Edu would be to switch PowerDNS to strict
165 mode and not use any of the existing objectclasses (dnsdomain,
166 dnsdomain2 and dnszone) when one want to combine the DNS information
167 with DHCP information, and instead create a auxiliary object class
168 defined something like this (using the attributes defined for
169 dnsdomain and dnsdomain2 or dnszone):</p>
170
171 <blockquote><pre>
172 objectclass ( some-oid NAME 'dnsDomainAux'
173 SUP top
174 AUXILIARY
175 MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAMERecord $
176 DNSTTL $ DNSClass $ PTRRecord $ HINFORecord $ MINFORecord $
177 TXTRecord $ SIGRecord $ KEYRecord $ AAAARecord $ LOCRecord $
178 NXTRecord $ SRVRecord $ NAPTRRecord $ KXRecord $ CERTRecord $
179 A6Record $ DNAMERecord
180 ))
181 </pre></blockquote>
182
183 <p>This will allow any object to become a DNS entry when combined with
184 the domainrelatedobject object class, and allow any entity to include
185 all the attributes PowerDNS wants. I've sent an email to the PowerDNS
186 developers asking for their view on this schema and if they are
187 interested in providing such schema with PowerDNS, and I hope my
188 message will be accepted into their mailing list soon.</p>
189
190 <p><strong>ISC dhcp</strong></p>
191
192 <p>The DHCP server searches for specific objectclass and requests all
193 the object attributes, and then uses the attributes it want. This
194 make it harder to figure out exactly what attributes are used, but
195 thanks to the working example in Debian Edu I can at least get an idea
196 what is needed without having to read the source code.</p>
197
198 <p>In the DHCP server configuration, the LDAP base to use and the
199 search filter to use to locate the correct dhcpServer entity is
200 stored. These are the relevant entries from
201 /etc/dhcp3/dhcpd.conf:</p>
202
203 <blockquote><pre>
204 ldap-base-dn "dc=skole,dc=skolelinux,dc=no";
205 ldap-dhcp-server-cn "dhcp";
206 </pre></blockquote>
207
208 <p>The DHCP server uses this information to nest all the DHCP
209 configuration it need. The cn "dhcp" is located using the given LDAP
210 base and the filter "(&(objectClass=dhcpServer)(cn=dhcp))". The
211 search result is this entry:</p>
212
213 <blockquote><pre>
214 dn: cn=dhcp,dc=skole,dc=skolelinux,dc=no
215 cn: dhcp
216 objectClass: top
217 objectClass: dhcpServer
218 dhcpServiceDN: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
219 </pre></blockquote>
220
221 <p>The content of the dhcpServiceDN attribute is next used to locate the
222 subtree with DHCP configuration. The DHCP configuration subtree base
223 is located using a base scope search with base "cn=DHCP
224 Config,dc=skole,dc=skolelinux,dc=no" and filter
225 "(&(objectClass=dhcpService)(|(dhcpPrimaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)(dhcpSecondaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)))".
226 The search result is this entry:</p>
227
228 <blockquote><pre>
229 dn: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
230 cn: DHCP Config
231 objectClass: top
232 objectClass: dhcpService
233 objectClass: dhcpOptions
234 dhcpPrimaryDN: cn=dhcp, dc=skole,dc=skolelinux,dc=no
235 dhcpStatements: ddns-update-style none
236 dhcpStatements: authoritative
237 dhcpOption: smtp-server code 69 = array of ip-address
238 dhcpOption: www-server code 72 = array of ip-address
239 dhcpOption: wpad-url code 252 = text
240 </pre></blockquote>
241
242 <p>Next, the entire subtree is processed, one level at the time. When
243 all the DHCP configuration is loaded, it is ready to receive requests.
244 The subtree in Debian Edu contain objects with object classes
245 top/dhcpService/dhcpOptions, top/dhcpSharedNetwork/dhcpOptions,
246 top/dhcpSubnet, top/dhcpGroup and top/dhcpHost. These provide options
247 and information about netmasks, dynamic range etc. Leaving out the
248 details here because it is not relevant for the focus of my
249 investigation, which is to see if it is possible to merge dns and dhcp
250 related computer objects.</p>
251
252 <p>When a DHCP request come in, LDAP is searched for the MAC address
253 of the client (00:00:00:00:00:00 in this example), using a subtree
254 scoped search with "cn=DHCP Config,dc=skole,dc=skolelinux,dc=no" as
255 the base and "(&(objectClass=dhcpHost)(dhcpHWAddress=ethernet
256 00:00:00:00:00:00))" as the filter. This is what a host object look
257 like:</p>
258
259 <blockquote><pre>
260 dn: cn=hostname,cn=group1,cn=THINCLIENTS,cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
261 cn: hostname
262 objectClass: top
263 objectClass: dhcpHost
264 dhcpHWAddress: ethernet 00:00:00:00:00:00
265 dhcpStatements: fixed-address hostname
266 </pre></blockquote>
267
268 <p>There is less flexiblity in the way LDAP searches are done here.
269 The object classes need to have fixed names, and the configuration
270 need to be stored in a fairly specific LDAP structure. On the
271 positive side, the invidiual dhcpHost entires can be anywhere without
272 the DN pointed to by the dhcpServer entries. The latter should make
273 it possible to group all host entries in a subtree next to the
274 configuration entries, and this subtree can also be shared with the
275 DNS server if the schema proposed above is combined with the dhcpHost
276 structural object class.
277
278 <p><strong>Conclusion</strong></p>
279
280 <p>The PowerDNS implementation seem to be very flexible when it come
281 to which LDAP schemas to use. While its "tree" mode is rigid when it
282 come to the the LDAP structure, the "strict" mode is very flexible,
283 allowing DNS objects to be stored anywhere under the base cn specified
284 in the configuration.</p>
285
286 <p>The DHCP implementation on the other hand is very inflexible, both
287 regarding which LDAP schemas to use and which LDAP structure to use.
288 I guess one could implement ones own schema, as long as the
289 objectclasses and attributes have the names used, but this do not
290 really help when the DHCP subtree need to have a fairly fixed
291 structure.</p>
292
293 <p>Based on the observed behaviour, I suspect a LDAP structure like
294 this might work for Debian Edu:</p>
295
296 <blockquote><pre>
297 ou=services
298 cn=machine-info (dhcpService) - dhcpServiceDN points here
299 cn=dhcp (dhcpServer)
300 cn=dhcp-internal (dhcpSharedNetwork/dhcpOptions)
301 cn=10.0.2.0 (dhcpSubnet)
302 cn=group1 (dhcpGroup/dhcpOptions)
303 cn=dhcp-thinclients (dhcpSharedNetwork/dhcpOptions)
304 cn=192.168.0.0 (dhcpSubnet)
305 cn=group1 (dhcpGroup/dhcpOptions)
306 ou=machines - PowerDNS base points here
307 cn=hostname (dhcpHost/domainrelatedobject/dnsDomainAux)
308 </pre></blockquote>
309
310 <P>This is not tested yet. If the DHCP server require the dhcpHost
311 entries to be in the dhcpGroup subtrees, the entries can be stored
312 there instead of a common machines subtree, and the PowerDNS base
313 would have to be moved one level up to the machine-info subtree.</p>
314
315 <p>The combined object under the machines subtree would look something
316 like this:</p>
317
318 <blockquote><pre>
319 dn: dc=hostname,ou=machines,cn=machine-info,dc=skole,dc=skolelinux,dc=no
320 dc: hostname
321 objectClass: top
322 objectClass: dhcpHost
323 objectclass: domainrelatedobject
324 objectclass: dnsDomainAux
325 associateddomain: hostname.intern
326 arecord: 10.11.12.13
327 dhcpHWAddress: ethernet 00:00:00:00:00:00
328 dhcpStatements: fixed-address hostname.intern
329 </pre></blockquote>
330
331 </p>One could even add the LTSP configuration associated with a given
332 machine, as long as the required attributes are available in a
333 auxiliary object class.</p>
334 </div>
335
336 <div class="tags">Tags: <a href="http://people.skolelinux.org/pere/blog/tags/debian">debian</a>, <a href="http://people.skolelinux.org/pere/blog/tags/debian edu">debian edu</a>, <a href="http://people.skolelinux.org/pere/blog/tags/english">english</a>, <a href="http://people.skolelinux.org/pere/blog/tags/ldap">ldap</a>, <a href="http://people.skolelinux.org/pere/blog/tags/nuug">nuug</a>.</div>
337
338 </div>
339
340
341
342
343
344
345 <div id="sidebar">
346
347 <h2>Archive</h2>
348 <ul>
349
350 <li>2011
351 <ul>
352
353 <li><a href="http://people.skolelinux.org/pere/blog/archive/2011/01/">January (3)</a></li>
354
355 </ul></li>
356
357 <li>2010
358 <ul>
359
360 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/01/">January (2)</a></li>
361
362 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/02/">February (1)</a></li>
363
364 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/03/">March (3)</a></li>
365
366 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/04/">April (3)</a></li>
367
368 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/05/">May (9)</a></li>
369
370 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/06/">June (14)</a></li>
371
372 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/07/">July (12)</a></li>
373
374 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/08/">August (13)</a></li>
375
376 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/09/">September (7)</a></li>
377
378 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/10/">October (9)</a></li>
379
380 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/11/">November (13)</a></li>
381
382 <li><a href="http://people.skolelinux.org/pere/blog/archive/2010/12/">December (12)</a></li>
383
384 </ul></li>
385
386 <li>2009
387 <ul>
388
389 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/01/">January (8)</a></li>
390
391 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/02/">February (8)</a></li>
392
393 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/03/">March (12)</a></li>
394
395 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/04/">April (10)</a></li>
396
397 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/05/">May (9)</a></li>
398
399 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/06/">June (3)</a></li>
400
401 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/07/">July (4)</a></li>
402
403 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/08/">August (3)</a></li>
404
405 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/09/">September (1)</a></li>
406
407 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/10/">October (2)</a></li>
408
409 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/11/">November (3)</a></li>
410
411 <li><a href="http://people.skolelinux.org/pere/blog/archive/2009/12/">December (3)</a></li>
412
413 </ul></li>
414
415 <li>2008
416 <ul>
417
418 <li><a href="http://people.skolelinux.org/pere/blog/archive/2008/11/">November (5)</a></li>
419
420 <li><a href="http://people.skolelinux.org/pere/blog/archive/2008/12/">December (7)</a></li>
421
422 </ul></li>
423
424 </ul>
425
426
427
428 <h2>Tags</h2>
429 <ul>
430
431 <li><a href="http://people.skolelinux.org/pere/blog/tags/3d-printer">3d-printer (13)</a></li>
432
433 <li><a href="http://people.skolelinux.org/pere/blog/tags/amiga">amiga (1)</a></li>
434
435 <li><a href="http://people.skolelinux.org/pere/blog/tags/aros">aros (1)</a></li>
436
437 <li><a href="http://people.skolelinux.org/pere/blog/tags/bitcoin">bitcoin (2)</a></li>
438
439 <li><a href="http://people.skolelinux.org/pere/blog/tags/bootsystem">bootsystem (10)</a></li>
440
441 <li><a href="http://people.skolelinux.org/pere/blog/tags/debian">debian (46)</a></li>
442
443 <li><a href="http://people.skolelinux.org/pere/blog/tags/debian edu">debian edu (54)</a></li>
444
445 <li><a href="http://people.skolelinux.org/pere/blog/tags/english">english (82)</a></li>
446
447 <li><a href="http://people.skolelinux.org/pere/blog/tags/fiksgatami">fiksgatami (1)</a></li>
448
449 <li><a href="http://people.skolelinux.org/pere/blog/tags/fildeling">fildeling (11)</a></li>
450
451 <li><a href="http://people.skolelinux.org/pere/blog/tags/kart">kart (5)</a></li>
452
453 <li><a href="http://people.skolelinux.org/pere/blog/tags/ldap">ldap (8)</a></li>
454
455 <li><a href="http://people.skolelinux.org/pere/blog/tags/lenker">lenker (4)</a></li>
456
457 <li><a href="http://people.skolelinux.org/pere/blog/tags/ltsp">ltsp (1)</a></li>
458
459 <li><a href="http://people.skolelinux.org/pere/blog/tags/multimedia">multimedia (11)</a></li>
460
461 <li><a href="http://people.skolelinux.org/pere/blog/tags/norsk">norsk (97)</a></li>
462
463 <li><a href="http://people.skolelinux.org/pere/blog/tags/nuug">nuug (114)</a></li>
464
465 <li><a href="http://people.skolelinux.org/pere/blog/tags/opphavsrett">opphavsrett (18)</a></li>
466
467 <li><a href="http://people.skolelinux.org/pere/blog/tags/personvern">personvern (32)</a></li>
468
469 <li><a href="http://people.skolelinux.org/pere/blog/tags/reprap">reprap (11)</a></li>
470
471 <li><a href="http://people.skolelinux.org/pere/blog/tags/robot">robot (4)</a></li>
472
473 <li><a href="http://people.skolelinux.org/pere/blog/tags/rss">rss (1)</a></li>
474
475 <li><a href="http://people.skolelinux.org/pere/blog/tags/sikkerhet">sikkerhet (22)</a></li>
476
477 <li><a href="http://people.skolelinux.org/pere/blog/tags/sitesummary">sitesummary (3)</a></li>
478
479 <li><a href="http://people.skolelinux.org/pere/blog/tags/standard">standard (21)</a></li>
480
481 <li><a href="http://people.skolelinux.org/pere/blog/tags/stavekontroll">stavekontroll (1)</a></li>
482
483 <li><a href="http://people.skolelinux.org/pere/blog/tags/surveillance">surveillance (5)</a></li>
484
485 <li><a href="http://people.skolelinux.org/pere/blog/tags/video">video (17)</a></li>
486
487 <li><a href="http://people.skolelinux.org/pere/blog/tags/vitenskap">vitenskap (1)</a></li>
488
489 <li><a href="http://people.skolelinux.org/pere/blog/tags/web">web (14)</a></li>
490
491 </ul>
492
493 </div>
494 </body>
495 </html>