aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2020-06-20 14:15:49 +0200
committerMartin Schanzenbach <mschanzenbach@posteo.de>2020-06-20 14:15:49 +0200
commitd646b828b4f3bb9b55efcf808f41e7d77162c497 (patch)
treec014e2877bb5fd2223a8b8c2cc00e9089abfd633
parent65f3ab13445b1abe2a0a93aa322746601531c39e (diff)
parent0265f9d718ad366f0153789011e871bc15d8dd9a (diff)
downloadwww-d646b828b4f3bb9b55efcf808f41e7d77162c497.tar.gz
www-d646b828b4f3bb9b55efcf808f41e7d77162c497.zip
Merge branch 'master' of git+ssh://gnunet.org/www
-rw-r--r--template/use.html.j2178
1 files changed, 95 insertions, 83 deletions
diff --git a/template/use.html.j2 b/template/use.html.j2
index fda9b6a7..75c7c52c 100644
--- a/template/use.html.j2
+++ b/template/use.html.j2
@@ -23,15 +23,15 @@
23 <div class="col"> 23 <div class="col">
24 <section> 24 <section>
25 <p> 25 <p>
26 This document is just a brief intro on what can be done with GNUnet. Find much more in our <a ref="https://docs.gnunet.org/">documentation</a>, e.g. in the section <a href="https://docs.gnunet.org/handbook/gnunet.html#toc-Using-GNUnet-1">"using GNUnet"</a> in the handbook. 26 This document is just a brief introduction on what can be done with GNUnet. Find out much more in our <a ref="https://docs.gnunet.org/">documentation</a>, e.g. in the section <a href="https://docs.gnunet.org/handbook/gnunet.html#toc-Using-GNUnet-1">"using GNUnet"</a> in the handbook.
27 27
28 The configuration in the handbook is done with the UI interface gnunet-gtk. 28 Please note that the handbook / reference manual uses the graphical user interface (UI) gnunet-gtk to configure GNUnet. In this introduction, we use the command line interface (CLI).
29 </p> 29 </p>
30 </section> 30 </section>
31 31
32<section> 32<section>
33 33
34 <h3>{{ _("Get on GNUnet") }}</h3> 34 <h3>{{ _("Accessing GNUnet") }}</h3>
35 35
36 <p> 36 <p>
37 Now we can start it with the command line tool 37 Now we can start it with the command line tool
@@ -75,7 +75,7 @@
75 vpn (gnunet-service-vpn) 75 vpn (gnunet-service-vpn)
76 </code> 76 </code>
77 77
78 <h3>{{ _("Get off GNUnet") }}</h3> 78 <h3>{{ _("Leaving GNUnet") }}</h3>
79 <p> 79 <p>
80 For stopping GNUnet again we can use the `-e` option; e=end. 80 For stopping GNUnet again we can use the `-e` option; e=end.
81 </p> 81 </p>
@@ -97,6 +97,8 @@
97 Tue Oct 30 19:58:48 2018: connection established 7WRD (timeout in 299 s)<br> 97 Tue Oct 30 19:58:48 2018: connection established 7WRD (timeout in 299 s)<br>
98 Tue Oct 30 19:58:48 2018: connection established 5WBG (timeout in 299 s)<br> 98 Tue Oct 30 19:58:48 2018: connection established 5WBG (timeout in 299 s)<br>
99 </code> 99 </code>
100
101 <p>Overtime the list will change as new peers connect or drop out, this is normal.</p>
100 </p> 102 </p>
101 There are much more options to see if you are connected and how. E.g. 'gnunet-peerinfo' shows you all peers your peer knows, or with "tail -f ~/.cache/gnunet/*" you'll get to see what's going on with your node. 103 There are much more options to see if you are connected and how. E.g. 'gnunet-peerinfo' shows you all peers your peer knows, or with "tail -f ~/.cache/gnunet/*" you'll get to see what's going on with your node.
102 </section> 104 </section>
@@ -104,7 +106,7 @@
104 <section> 106 <section>
105 <h3>{{ _("... and play around with it.") }}</h3> 107 <h3>{{ _("... and play around with it.") }}</h3>
106 <p> 108 <p>
107 So let's try out some of GNUnet's use cases. Please mind that some should be done in a particular order, one after another: 109 So let's try out some of GNUnet's most common use-cases to illustrate it's power. Please be mindful that some should be done in a particular order, one after another:
108 </p> 110 </p>
109 111
110 <ul> 112 <ul>
@@ -139,7 +141,7 @@
139 </code> 141 </code>
140 </p> 142 </p>
141 <p> 143 <p>
142 Finding the file by keyword works with `gnunet-search`. 144 GNUnet users can find the file by using the <code>gnunet-search</code> command.
143 </p> 145 </p>
144 <p> 146 <p>
145 <code> 147 <code>
@@ -149,22 +151,21 @@
149 </code> 151 </code>
150 </p> 152 </p>
151 <p> 153 <p>
152 It gives us the command line call to download the file (and store it as 154 <code>gnunet-search</code> returns the command line call to download the file (and store it as ostrom.pdf)!
153 ostrom.pdf)!
154 </p> 155 </p>
155 <p> 156 <p>
156 <p> 157 <p>
157 It's recommended for filesharing that you increase your bandwidth restrictions 158 It's recommended for filesharing that you increase GNUnet's bandwidth restrictions
158 from the actually pretty low defaults. The example below sets the WAN 159 from the actually pretty low defaults. The example below sets the WAN
159 and LAN limits to the value "unlimited". 160 and LAN limits to the value "unlimited".
160 </p> 161 </p>
161 162
162 <code> 163 <code>
163 $ gnunet-config -s ats -o WAN_QUOTA_IN -V unlimited<br /> 164 $ gnunet-config -s ats -o WAN_QUOTA_IN -V unlimited<br />
164 $ gnunet-config -s ats -o WAN_QUOTA_OUT -V unlimited<br /> 165 $ gnunet-config -s ats -o WAN_QUOTA_OUT -V unlimited<br />
165 $ gnunet-config -s ats -o LAN_QUOTA_IN -V unlimited<br /> 166 $ gnunet-config -s ats -o LAN_QUOTA_IN -V unlimited<br />
166 $ gnunet-config -s ats -o LAN_QUOTA_OUT -V unlimited<br /> 167 $ gnunet-config -s ats -o LAN_QUOTA_OUT -V unlimited<br />
167 </code> 168 </code>
168 </p> 169 </p>
169 <p> 170 <p>
170 Please note that it might take some time (up to some hours) till your peers can see your freshly uploaded files. 171 Please note that it might take some time (up to some hours) till your peers can see your freshly uploaded files.
@@ -174,38 +175,41 @@
174 175
175 </section> 176 </section>
176 177
177
178
179 <section> 178 <section>
180
181 <h3><a name="cadet" class="subnav-anchor"></a>{{ _("CADET (and Chat)") }}</h3> 179 <h3><a name="cadet" class="subnav-anchor"></a>{{ _("CADET (and Chat)") }}</h3>
180 <p>The CADET subsystem is at the heart of the GNUnet project because it is responsible for secure end-to-end communications between peers (nodes) in the GNUnet overlay network.</p>
182 <p> 181 <p>
183 We can use the `gnunet-cadet` command line tool to open a port and from 182 Users can chat and send files to each other on the GNUnet network using a simple CADET tool. We use the `gnunet-cadet` command line tool to open a port on our local machine and from another peer on the network connect to this port. Users can then chat or transfer files.
184 another machine connect to this port and chat or transfer data. First we need 183 </p>
185 our <b>peer ID</b> of the GNUnet peer opening the port. 184
186 </p> 185 <p>
186 In the following example, Alice will create a CADET session on her laptop. Bob will then connect to Alice from his desktop. Alice will first need her <b>peer ID</b> of the GNUnet and provide it to Bob.
187 </p>
187 <p> 188 <p>
188 <code> 189 <code>
189 $ gnunet-peerinfo -s<br> 190 alice@laptop $ gnunet-peerinfo -s<br>
190 I am peer `P4T5GHS1PCZ06R82D3KW8Z8J1113BQZWAWGYHTZ8G1ZXMWXQGAVG'. 191 I am peer `P4T5GHS1PCZ06R82D3KW8Z8J1113BQZWAWGYHTZ8G1ZXMWXQGAVG'.
191 </code> 192 </code>
192 </p> 193 </p>
193 <p> 194 <p>
194 Now we open the port (it can be any string!): 195 Now Alice will open a port using the -o option, giving it a name, in this case Alice calls it 'my-secret-port' (it can be any string!):
195 </p> 196 </p>
196 <p> 197 <p>
197 <code> 198 <code>
198 $ gnunet-cadet -o my-secret-port 199 alice@laptop $ gnunet-cadet -o my-secret-port
199 </code> 200 </code>
200 </p> 201 </p>
201 <p>On the other machine we can connect using the peer ID and the port and start chatting! "Other machine can be a friend's one which has GNUnet running, but it can also just be another shell on your machine.</p> 202 <p>On Bob's machine he can connect to Alice using her <b>peer ID</b> and the port name. Once connected they can start chatting.</p>
202 <p> 203 <p>
203 <code> 204 <code>
204 $ gnunet-cadet P4T5GHS1PCZ06R82D3KW8Z8J1113BQZWAWGYHTZ8G1ZXMWXQGAVG my-secret-port 205 bob@desktop $ gnunet-cadet P4T5GHS1PCZ06R82D3KW8Z8J1113BQZWAWGYHTZ8G1ZXMWXQGAVG my-secret-port
205 </code> 206 </code>
206 </p> 207 </p>
208
209 <p>It's worth nothing that the other peers can be a friend's machine which has GNUnet running, or it can also just be another shell on your own machine.</p>
210
207 <p> 211 <p>
208 If you are interested into CADET in detail, please have a look in the <a href="https://docs.gnunet.org/handbook/gnunet.html#CADET-Subsystem">chapter "Cadet-Subsystem" in our handbook</a>. The CADET subsystem is responsible for secure end-to-end communications between nodes in the GNUnet overlay network; as transport protocol it's somewhat of the heart of the project. 212 If you are interested in the details of CADET, please read the <a href="https://docs.gnunet.org/handbook/gnunet.html#CADET-Subsystem">"Cadet-Subsystem" chapter in the GNUnet handbook</a>.
209 </p> 213 </p>
210 </section> 214 </section>
211 215
@@ -214,25 +218,25 @@
214 <section> 218 <section>
215 <h3><a name="groupchat" class="subnav-anchor"></a>{{ _("Chatting with a (simple) client") }}</h3> 219 <h3><a name="groupchat" class="subnav-anchor"></a>{{ _("Chatting with a (simple) client") }}</h3>
216 <p> 220 <p>
217 To chat a tiny bit prettier, we can install and compile additional software. 221 To make chatting a tiny bit easier and prettier, we need to install and compile additional software.
218 If you join the chat mentioned below and no one is there, feel free to ping on 222 If you join the chat mentioned below and no one is there, feel free to ping on
219 IRC/freenode #gnunet and ask if someone can join to test with you! (But we are 223 IRC/freenode #gnunet and ask if someone can join in to test with you! (But we are
220 trying to be there as often as possible). 224 trying to be there as often as possible).
221 </p> 225 </p>
222 <p> 226 <p>
223 First we have to install Nim. Please refer to their <a href="https://nim-lang.org/install.html">project site</a> for further details. The preferred method is using our package manager, e.g. for Debian it would look like this: 227 First we have to install the Nim programming language. Please refer to their <a href="https://nim-lang.org/install.html">project site</a> for further details. The preferred method is using you distributions package manager, e.g. for Debian it would look like this:
224 </p> 228 </p>
225 <code> 229 <code>
226 $ sudo apt install nim<br> 230 $ sudo apt install nim<br>
227 $ nim --version<br> 231 $ nim --version<br>
228 Nim Compiler Version 0.20.2 [Linux: amd64]<br> 232 Nim Compiler Version 1.2.2 [Linux: amd64]<br>
229 Compiled at 2019-07-17<br> 233 Compiled at 2020-06-16<br>
230 Copyright (c) 2006-2019 by Andreas Rumpf<br> 234 Copyright (c) 2006-2020 by Andreas Rumpf<br>
231 <br> 235 <br>
232 active boot switches: -d:release -d:nativeStackTrace<br> 236 active boot switches: -d:release -d:nativeStackTrace<br>
233 </code> 237 </code>
234 <p> 238 <p>
235 If the displayed version is <b>0.19.0 or newer</b>, we have a compatible version and can continue downloading and compiling the groupchat. If the version is older (like on Ubuntu 18.04) we can install Nim using a tool called <i>choosenim</i>: 239 If the displayed version is <b>1.2.2 or newer</b>, we have a compatible version and can continue downloading and compiling the groupchat. If the version is older (like on Ubuntu 18.04) we can install Nim using a tool called <i>choosenim</i>:
236 </p> 240 </p>
237 <code> 241 <code>
238 $ curl https://nim-lang.org/choosenim/init.sh -sSf | sh 242 $ curl https://nim-lang.org/choosenim/init.sh -sSf | sh
@@ -243,11 +247,11 @@
243 <p>In the onscreen instructions you'll be ask to add a line to your bashrc - once you've done that, re-read your bash environment to make the change active: 247 <p>In the onscreen instructions you'll be ask to add a line to your bashrc - once you've done that, re-read your bash environment to make the change active:
244 </p> 248 </p>
245 <code> 249 <code>
246 source ~/.bashrc 250 $ source ~/.bashrc
247 </code> 251 </code>
248 252
249 <p> 253 <p>
250 After we have installed (and maybe upgraded) Nim we download and compile the groupchat application: 254 After we have installed (and maybe upgraded) Nim we download and compile the GNUnet groupchat application:
251 </p> 255 </p>
252 <p> 256 <p>
253 <code> 257 <code>
@@ -257,50 +261,55 @@
257 </code> 261 </code>
258 <p> 262 <p>
259 <p> 263 <p>
260 Fine! We can now try to enter a chat server running on another GNUnet node. 264 We can now try to enter a chat server running on another GNUnet node using the command:
261 </p> 265 </p>
262 <p> 266 <p>
263 <code> 267 <code>
264 $ LD_LIBRARY_PATH=/path/to/gnunetlibs ./groupchat --config=/path/to/gnunet.conf --server=88RXABKJNMT426FY81N2DXN0M2X37SW5Q1NR005YPDZ1Q7A22CHG --port=t3ss --nick=YOURNICK<br> 268 $ LD_LIBRARY_PATH=/path/to/gnunetlibs ./groupchat --config=/path/to/gnunet.conf --server=88RXABKJNMT426FY81N2DXN0M2X37SW5Q1NR005YPDZ1Q7A22CHG --port=t3ss --nick=YOURNICK<br>
265 </code> 269 </code>
266 <p> 270 <p>
267 The peer and port in this example should almost always be online and running groupchat on that port. 271 The peer key and port name given in this example should work as they are almost always online and running groupchat on port "t3ss".
268 </p> 272 <p>
269 </section> 273 </section>
270 274
271 275
272 276
273 <section> 277 <section>
274 <h3><a name="gns_cli" class="subnav-anchor"></a>{{ _("Name resolution using GNS on the command line") }}</h3> 278 <h3><a name="gns_cli" class="subnav-anchor"></a>{{ _("Name resolution using GNS on the command line") }}</h3>
275 <p>GNS is the GNU name service, a fully decentralized alternatice to DNS. We'll publish an IP address in a GNS record try to resolve it on the command line. First we need an identity which is the 279 <p>The GNU Name Service (GNS) is a fully decentralized alternative to the Domain Name System (DNS). Where GNS does not suffer the same major <a href="https://en.wikipedia.org/wiki/Domain_Name_System#Security_issues">security flaws as DNS</a>.
276 equivalent to a zone in DNS. We'll call it "myself" and create it using the 280 </p>
277 `gnunet-identity` command line tool. Instead of "myself" you can surely use your 281
278 nick or any other name. </p> 282 <p>
283 In this example, Alice will save the IP address (195.54.164.39) of the Chaos Computer Club e.V. (CCC) homepage into a GNUnet namestore record and then try to resolve it using GNUnet GNS.
284
285
286 <p> First Alice needs to create a GNUnet identity which is the equivalent to a zone in a DNS. We'll call it "myself" and create it using the `gnunet-identity` command line tool. Instead of "myself" you can use your nickname, or any other name. </p>
287
279 <p> 288 <p>
280 <code> 289 <code>
281 $ gnunet-identity -C myself 290 alice@laptop $ gnunet-identity -C myself
282 </code> 291 </code>
283 </p> 292 </p>
284 <p>We can check if it worked using the same tool. We expect the name of our identity and the corresponding public key to be displayed.</p> 293
294 <p>Alice can check to see if it worked using the same tool. The name of her identity and the corresponding public key are displayed.</p>
285 <p> 295 <p>
286 <code> 296 <code>
287 $ gnunet-identity -d<br> 297 alice@laptop $ gnunet-identity -d<br>
288 myself - HWTYD3P5D77JVFNVMZ1M5T10V4SZYNMY3PCGQCSVENKD6ZCRKPMG 298 myself - HWTYD3P5D77JVFNVMZ1M5T10V4SZYNMY3PCGQCSVENKD6ZCRKPMG
289 </code> 299 </code>
290 </p> 300 </p>
291 <p> 301 <p>
292 Now we add a public `A` record to our zone. It has the name "ccc", a value 302 Now Alice adds a public `A` record to the zone. We'll call it "ccc" with the value "195.54.164.39" and it expires after one day.
293 of "195.54.164.39" and it expires after one day.
294 </p> 303 </p>
295 <p> 304 <p>
296 <code> 305 <code>
297 $ gnunet-namestore -z myself -a -e "1 d" -p -t A -n ccc -V 195.54.164.39 306 alice@laptop $ gnunet-namestore -z myself -a -e "1 d" -p -t A -n ccc -V 195.54.164.39
298 </code> 307 </code>
299 </p> 308 </p>
300 <p>Now we can query that record using the command line tool `gnunet-gns`.</p> 309 <p>Now the GNS can be queried using the command line tool `gnunet-gns`.</p>
301 <p> 310 <p>
302 <code> 311 <code>
303 $ gnunet-gns -t A -u ccc.myself<br> 312 alice@laptop $ gnunet-gns -t A -u ccc.myself<br>
304 ccc.myself:<br> 313 ccc.myself:<br>
305 Got `A' record: 195.54.164.39 314 Got `A' record: 195.54.164.39
306 </code> 315 </code>
@@ -313,13 +322,13 @@
313 </p> 322 </p>
314 <p> 323 <p>
315 <code> 324 <code>
316 $ gnunet-namestore -z myself -a -e never -p -t PKEY -n alice -V HWTYD3P5D77JVFNVMZ1M5T10V4SZYNMY3PCGQCSVENKD6ZCRKPMG 325 bob@desktop $ gnunet-namestore -z myself -a -e never -p -t PKEY -n alice -V HWTYD3P5D77JVFNVMZ1M5T10V4SZYNMY3PCGQCSVENKD6ZCRKPMG
317 </code> 326 </code>
318 </p> 327 </p>
319 <p> 328 <p>
320 Our identity in Bobs namestore is a public record (-p) and never 329 Alices identity in Bobs namestore is a public record (-p) and never
321 expires (-e never). Now Bob (let's assume he has called his 330 expires (-e never). Now Bob (let's assume he has called his
322 identity myself, too) should be able to resolve our "ccc" record, 331 identity myself, too) should be able to resolve Alice's "ccc" record,
323 too! 332 too!
324 </p> 333 </p>
325 <p> 334 <p>
@@ -331,9 +340,9 @@
331 </p> 340 </p>
332 <p> 341 <p>
333 It can continue like this. A friend of Bob would be able to 342 It can continue like this. A friend of Bob would be able to
334 resolve our records too because Bob published our identity in a 343 resolve Alice's records too because Bob published her identity in a
335 public record. Bobs friend would simply use "ccc.alice.bob.myself" 344 public record. Bobs friend would simply use "ccc.alice.bob.myself"
336 to resolve our "ccc" record. 345 to resolve Alice's "ccc" record.
337 </p> 346 </p>
338 <p> 347 <p>
339 See the <a href="https://docs.gnunet.org/handbook/gnunet.html#First-steps-_002d-Using-the-GNU-Name-System">chapter "Using the GNU Name System" in our handbook</a> for a more detailed documentation. 348 See the <a href="https://docs.gnunet.org/handbook/gnunet.html#First-steps-_002d-Using-the-GNU-Name-System">chapter "Using the GNU Name System" in our handbook</a> for a more detailed documentation.
@@ -346,18 +355,25 @@
346 <h3><a name="gns_browser" class="subnav-anchor"></a>{{ _("Name resolution using GNS with a browser") }}</h3> 355 <h3><a name="gns_browser" class="subnav-anchor"></a>{{ _("Name resolution using GNS with a browser") }}</h3>
347 356
348 <p> 357 <p>
349 In the previous use case "Name resolution using GNS on the command line" we got an idea 358 In the previous use-case "Name resolution using GNS on the command line" we saw how we could retrieve a value (e.g. an IP address) associated with a given named record (e.g. a web address).
350 about what GNS is about, but now let's use it with a browser, to make it actually useful. Currently Firefox and Chromium are known to work. 359 Now we'll see how GNS can be used with a browser, making it actually useful. Currently Firefox and Chromium are known to work with GNS.
351 </p> 360 </p>
352 361
353 <p> 362 <p>
354 Many websites enforce HTTPS and thus provide certificates for 363 Many websites enforce HTTPS by providing TLS certificates for
355 their hostnames (and not our GNS names). Browsers don't like wrong 364 their hostnames, with the aim of encrypting the web page content between the clients browser and the hostname server, and authenticating the server and client to each other. This is so
356 hostnames in certificates and will present error messages. So GNUnet 365 that a 3rd party cannot see what is being communicated between the client (browser) and server (website host). This is important, for example, if you are using online banking where you don't want anyone seeing your customer ID and password.
357 has to trick them by generating own certificates for our GNS
358 names. This means we need to create our own certificate authority
359 and tell our browser about it. Luckily there's a script for it:
360 </p> 366 </p>
367
368 <p>
369 Unfortunately, if a browser resolves a hostname through the GNS, the TLS certificates will have the original hostname and the browser will present an error message. In the previous example, we resolved "ccc.myself" to 195.54.164.39 but the hostname's TLS certificate refers to the actual hostname as "https://www.ccc.de/"
370
371 So GNUnet has to trick the browser by generating it's own certificates for the hostnames GNS
372 resolves. This means we need to create our own certificate authority
373 and tell our browser to use this instead. Luckily there's a script to fix this problem:
374 </p>
375
376
361 <p> 377 <p>
362 <code> 378 <code>
363 $ gnunet-gns-proxy-setup-ca 379 $ gnunet-gns-proxy-setup-ca
@@ -371,18 +387,19 @@
371 names with GNS first and forward the rest of the DNS traffic to 387 names with GNS first and forward the rest of the DNS traffic to
372 the system's DNS resolver. It will also take care of the HTTP 388 the system's DNS resolver. It will also take care of the HTTP
373 traffic, so the browser gets valid certificates and the web server 389 traffic, so the browser gets valid certificates and the web server
374 will not be confused by our GNS hostnames. Our GNS namestore 390 will not be confused by the hostnames resolved by GNS instead of the DNS. The GNS namestore
375 doesn't know about any DNS hostnames yet, so we have to store 391 does not know about any DNS hostnames yet, so we have to store
376 them, too. For our "ccc" A record, we have to store a LEHO (legacy 392 them, too. For our "ccc" A record, we have to store a LEHO (LEgacy
377 hostname) record, too. It must contain the website's original DNS 393 HOstname) record, too. It must contain the website's original DNS
378 hostname: 394 hostname:
379 </p> 395 </p>
396
380 <p> 397 <p>
381 <code> 398 <code>
382 $ gnunet-namestore -z myself -a -e "1 d" -p -t LEHO -n ccc -V www.ccc.de 399 $ gnunet-namestore -z myself -a -e "1 d" -p -t LEHO -n ccc -V www.ccc.de
383 </code> 400 </code>
384 </p> 401 </p>
385 <p>Now let's start gnunet-gns-proxy.</p> 402 <p>Now lets start gnunet-gns-proxy.</p>
386 <p> 403 <p>
387 <code> 404 <code>
388 $ /usr/lib/gnunet/libexec/gnunet-gns-proxy 405 $ /usr/lib/gnunet/libexec/gnunet-gns-proxy
@@ -522,7 +539,7 @@
522 </p> 539 </p>
523 540
524 <code> 541 <code>
525 gnunet-peerinfo -p <string> 542 $ gnunet-peerinfo -p <string>
526 </code> 543 </code>
527 544
528 <p> 545 <p>
@@ -551,9 +568,4 @@
551 </div> 568 </div>
552 </div> 569 </div>
553</article> 570</article>
554{% endblock body_content %} 571{% endblock body_content %} \ No newline at end of file
555
556
557
558
559