From b925f8cc1e5c26c266579aca1776a0dedeeb55b5 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 2 Feb 2016 13:30:33 +0000 Subject: [PATCH] Reseed: Add new go quick start guide from backup Move PHP docs to the bottom, mark not recommended Spelling fixes in overview --- i2p2www/pages/site/docs/reseed.html | 8 +- .../site/get-involved/guides/reseed.html | 1779 +++++++++-------- 2 files changed, 939 insertions(+), 848 deletions(-) diff --git a/i2p2www/pages/site/docs/reseed.html b/i2p2www/pages/site/docs/reseed.html index 29471bffe..1582892a9 100644 --- a/i2p2www/pages/site/docs/reseed.html +++ b/i2p2www/pages/site/docs/reseed.html @@ -8,7 +8,7 @@ <h2 id="about">{% trans %}About Reseed hosts{% endtrans %}</h2> <p>{% trans -%} -Reseed hosts are needed to for bootstrapping, that is providing the initial set of I2P nodes for your I2P node to talk to. Depending on the status of your node it may need to bootstrap every now and then if many of the nodes it knows of aren't contactable. +Reseed hosts are needed to for bootstrapping, that is, providing the initial set of I2P nodes for your I2P node to talk to. Depending on the status of your node it may need to bootstrap every now and then if many of the nodes it knows of aren't contactable. {%- endtrans %}</p> <p>{% trans -%} @@ -19,7 +19,7 @@ Reseeding is done over an encrypted connection and all of the bootstrap informat <h2 id="running">{% trans %}Running a Reseed host{% endtrans %}</h2> <p> {% trans -%} -The more reseed hosts that are run, the more resiliant the I2P network becomes, and the harder it is to prevent users of I2P from connecting to the network. +The more reseed hosts that are run, the more resilient the I2P network becomes, and the harder it is to prevent users of I2P from connecting to the network. {%- endtrans %} </p> {% trans -%} @@ -33,8 +33,8 @@ There have also been cases where the reseed hosts we had, have been under heavy <h2 id="thank you">{% trans %}Thank you{% endtrans %}</h2> <p> {%-trans -%} -If you are running a reseed server, I would like to thank you for helping to -make the I2P network stronger and more resiliant than ever. +If you are running a reseed server, We would like to thank you for helping to +make the I2P network stronger and more resilient than ever. {%- endtrans-%} </p> <p> diff --git a/i2p2www/pages/site/get-involved/guides/reseed.html b/i2p2www/pages/site/get-involved/guides/reseed.html index d838ffe97..ebe9951a4 100644 --- a/i2p2www/pages/site/get-involved/guides/reseed.html +++ b/i2p2www/pages/site/get-involved/guides/reseed.html @@ -99,58 +99,6 @@ Thank you! <h2>{% trans %}Detailed Instructions{% endtrans %}</h2> -<h3>Revision History</h3> -<pre> - -2015-10-08 backup -* self-signed ssl-certificate with EC signature + key -* updated start-script for matts solution - "seedserver" -* ==> howto_public_reseed_server_v7.txt - -2015-05-09 backup - * new chapter: reverse-proxy setup (idea by kytv and review from matt) - * ==> howto_public_reseed_server_v6.txt - -2015-03-23 backup (with much help from matt) - * Script - su3.php - added support for running INSIDE i2p-net (DESTB32) - * Script - su3.php - added proper html header for downloading in any browser - * Script - cronjob_i2p.sh - minor code cleanups - * Script - cronjob_i2p.sh - added FINAL CHECK number su3-files - * new chapter: Optional - setup a manual reseed method, secured by captcha - * new chapter: matt's go solution - Overview - * new chapter: matt's go solution - Building from source - * new chapter: matt's go solution - Run the reseed server - * new chapter: matt's go solution - Draft for startup script - * new chapter: matt's go solution - Convert existing Java keystore to crt- and pem-file - * ==> howto_public_reseed_server_v5.txt - -2015-01-22 backup - * Script - cronjob_i2p.sh - minor code cleanups with shell script validator/parser - * Script - su3.php - minor code cleanup (404 redirect), thanks to "drgr33n" - * we want only HTTPS accessible reseed server - * Testings - added some wget options for the ssl-certificate, thanks to "drgr33n" - * ==> howto_public_reseed_server_v4.txt - -2014-12-26 backup - * Script - cronjob_i2p.sh - config variable "target" without ending "/" - * meeh completely removed in contacts - * new chapter: reseed server domain/url/port exchange - * chapter "requirements" expanded - traffic volume, attacks, web server-port!=443 - * chapter "Create self-signed ssl-certificate" - use rsa, not ecdsa - * ==> howto_public_reseed_server_v3.txt - -2014-12-13 backup - * new chapter: Create self-signed ssl-certificate - * new chapter: Seamless ssl-cert exchange - * meeh's solution removed - * cronjob_i2p.sh: example target path changed to "/var/www/su3/" for clarification - * ==> howto_public_reseed_server_v2.txt - -2014-10-17 backup - * initial release v1 - -</pre> - <h3>How-to Public reseed servers - su3</h3> @@ -165,8 +113,34 @@ Thank you! <h3>Table of contents</h3> <ol> -<li>Intro +<li>Introduction <li>Requirements +<li>Go solution - Quick Guide +<ol> + <li>Start web server + <li>Install git and golang + <li>Build and test + <li>Run reseed + <li>Backup certificates and keys + <li>Enable autostart + <li>Connect web server to reseed + <li>Test from another computer + <li>Send us your certificates +</ol> + + +<li>Go solution -Detailed Guide +<ol> + <li>Go solution - Building from source + <li>Go solution - Run the reseed server + <li>Go solution - Draft for startup script + <li>Go solution - reverse-proxy setup + <li>Go solution - Convert existing Java keystore to crt- and pem-file +</ol> + + +<li>PHP solution - Not recommended +<ol> <li>Short overview <li>su3-file guidelines for reseeding <li>How to prepare your key pair for su3-files @@ -183,17 +157,12 @@ Thank you! <li>Script - cronjob_i2p.sh <li>Script - su3.php <li>Optional - setup a manual reseed method -<li>matt's go solution - Overview -<li>matt's go solution - Building from source -<li>matt's go solution - Run the reseed server -<li>matt's go solution - Draft for startup script -<li>matt's go solution - reverse-proxy setup -<li>matt's go solution - Convert existing Java keystore to crt- and pem-file +</ol> </ol> -<h3>1. Intro</h3> +<h2>1. Introduction</h2> <p> Public reseed servers are necessary to bootstrap into the I2P net. New installed I2P routers needs one-time about one hundred RouterInfo's (RI) as jump start. @@ -219,7 +188,7 @@ one su3-file within 24h for one client IP. </p> -<h3>2. Requirements</h3> +<h2>2. Requirements</h2> <p> Requirements for running a public reseed server: @@ -240,1104 +209,1226 @@ This How-to is tested with Ubuntu/Debian The web server has to be public reachable from all over the world, an eepsite inside I2P can be setup in addition. Also frequent or infrequent attempts to scrape all your reseed files, and of course attacks on your server. The web server doesn't need to listen at default SSL/TSL port 443 - any other port can be used for obfuscation. +</p> +<h2>3. Go solution - Quick Guide</h2> - -<h3>3. Short overview</h3> - -<ul> -<li>permanent: run your I2P router -<li>once: generate a private and public key pair for signing the reseed files -<li>once: setup the PHP script on the web server -<li>once: setup a rewrite rule at web server (*.su3 --> su3.php) -<li>regularly: run the Unix shell script to generate up-to-date su3-files -<li>regularly: transfer su3-files to local /var/www/ or with (s)ftp to your remote web server -</ul> +<h3>1. Fire up your favorite webserver</h3> +<ol><li> + connect a domain, sub-domain or (anonymous) third-level-domain +</li><li> + setup a state-of-the-art TLS(SSL) certificate +</li><li> + allow access only via HTTPS/TLS, no unencrypted HTTP +</li><li> + allow only very good ciphers, compatible to Java 7/8/9 +</li></ol> +<p> +Note: A non default port other than 443 can be used; TLS certificate can be self signed; configure fail2ban as bot-net protection +</p> +<h3>2. Install git and golang-go (1.4.2 or higher)</h3> +<pre> + sudo apt install git + sudo apt install golang-go +</pre> -<h3>4. su3-file guidelines for reseeding</h3> +<h3>3. Switch to user running i2p, fetch the i2p-tool source code, build and test it</h3> <p> -(From <a href="http://zzz.i2p/topics/1648">zzz.i2p</a>) -<ul> -<li>The su3-file must be named "i2pseeds.su3" -<li>The file must be in the same directory as the routerinfos on the web server -<li>Router will first try to fetch (index url)/i2pseeds.su3; - if that fails it will fetch (index url) and then fetch the individual RI files, old-style -<li>Once a reseed from a host succeeds, it won't try any other URLs from that host - (either http or https, ignoring ports... ports are now implemented) -<li>RI files in the zip file (in the su3-file) must be at the "top level", - i.e. no directories in the zip file -<li>su3 content type must be RESEED (-c 3 or -c RESEED) -<li>su3 signature type should be RSA 4096 (-t 6 or -t RSA_SHA512_4096). - If you're very low on CPU power you could use a shorter key, but you only need to do the signing process once a day or so. - Any sig type will work, but RSA 4096 is the best in this case. -<li>Of course we must have your su3 signing public key checked in - under the same name as you are using in the signing process, - e.g. for you@mail.i2p the file name must be you_at_mail.i2p.crt, in the certificates/reseed/ directory -</ul> +Note: Visit http://reseed.i2p and download a pre-build x86_64 binary, so you can skip step 2+3. +</p> +<pre> + export GOPATH=$HOME/go; mkdir $GOPATH; cd $GOPATH + go get github.com/martin61/i2p-tools + bin/i2p-tools -h +</pre> +<h3>4. Run i2p-tools locally</h3> +<pre> + GOPATH=$HOME/go; + cd $GOPATH; + bin/i2p-tools reseed --signer=yourname@mail.i2p --netdb=/home/i/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy +</pre> -<h3>5. How to prepare your key pair for su3-files</h3> +<h3>5. Back up new certificates</h3> <p> -( from <a href="http://zzz.i2p/topics/1643">zzz.i2p</a>) -<ul> -<li>Details are posted here from zzz: <a href="http://zzz.i2p/topics/1473">zzz.i2p</a> -<li>Who? All owner of a public reseed server. -<li>Why? su3 reseed files will be signed with your private key. -<li>This ensures a secure bootstrap for I2P routers. -<li>Corresponding public keys will be included in I2P router package. -</ul> + Make a backup from the new created su3-signing key and certificate found in $GOPATH and keep it in a save password protected storage +</p> -<p> -Example to create your key pair: + +<h3>6. enable autostart (+restart) for i2p-tools in your crontab</h3> <pre> - su - i2puser - I2P=/home/i2puser/i2p - cd $I2P - java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File keygen -t RSA_SHA512_4096 backup_at_mail.i2p.crt keystore.ks backup@mail.i2p + @reboot GOPATH=$HOME/go; cd $GOPATH; bin/i2p-tools reseed ... >/dev/null 2>&1 + 9 * * * * GOPATH=$HOME/go; cd $GOPATH; bin/i2p-tools reseed ... >/dev/null 2>&1 </pre> + +<h3>7. connect your webserver via reverse-proxy-setup to the i2p-tool, examples</h3> <p> -Short usage help: + lighttpd configuration example: +</p> <pre> - SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p + server.modules += ( "mod_proxy" ) + proxy.server = ( "i2pseeds.su3" => ( ( "host" => "127.0.0.1", "port" => 8443 ) ) ) </pre> <p> -Get more help: + nginx configuration example: +</p> <pre> - java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File + location / { + proxy_pass http://127.0.0.1:8443; + } </pre> <p> -Provide a strong password for your private key. -In this example two new files will be created in the working folder: -<ul> -<li>backup_at_mail.i2p.crt will contain the public key -<li>keystore.ks is the Java keystore file and contains your private key -</ul> + apache (sorry: untested - feedback would be appreciated) +</p> +<pre> + ProxyRequests Off + <Proxy *> + Order deny,allow + Allow from all + </Proxy> + ProxyPass / http://127.0.0.1:8443/ + ProxyPassReverse / http://127.0.0.1:8443/ +</pre> <p> -Backup and store public key, private key and your password! -Remember also the used key size/type when not using default RSA_SHA512_4096. -Send the public .crt key file to us, to include it into i2p/certificates/reseed/ -If you have mtn privs, you may check the (you)_at_mail.i2p.crt file directly into installer/resources/certificates/reseed . -The file name must be (email address used for signing).crt, with "@" replaced with "_at_". -There is no requirement that it be xxx@mail.i2p, any email is fine, or for that matter any identifier. +Note: i2p-tool has also an build-in standalone webserver with tls support which can be used without a webserver. +</p> +<h3>8. Final test from another computer with i2p running</h3> +<ol><li> + place your su3-certificate (*.crt) in i2p/certificates/reseed/ +</li><li> + place your tls-certificate (*.crt) in i2p/certificates/ssl/ +</li><li> + visit with your webbrowser http://localhost:7657/configreseed +</li><li> + enter your new reseed-url and delete all others, hit "Save changes and reseed now" +</li><li> + check the i2p logs for "Reseed got 77 router infos from ... with 0 errors, Reseed complete, 77 received" +</li></ol> -<h3>6. su3 server-side implementation</h3> - -<p> -(from <a href="http://zzz.i2p/topics/1647">zzz.i2p</a>) -This describes a mechanism for creating and distributing the RI in new su3 format. -It's independent from legacy way of doing (fetching dat-files) and can be used in parallel. -This idea doesn't need mysql, only some Unix shell tools and a simple web server with PHP works fine. +<h3>9. Send us your information</h3> +<ol><li> + domain/url/port +</li><li> + su3-signing certificate +</li><li> + tls certificate (if self signed) +</li></ol> -<p> -A requesting client gets ~75 RI packed into one zip, signed and converted to a su3-file. -Don't provide unlimited RI to one clients. -But don't try to keep track of million client IP's in a database, e.g think of ipv6. -Keep it simple: make a fix n:m one-direction matching: n*ip --> m*su3-file by modulo. -n is the unlimited IPv4+IPv6 address space, and m are e.g. 100 pre-calculated su3-files. -A client with one IP gets always the same su3-file, until the su3-file is updated or the client has a new IP. -A number of clients (n/m ratio) gets the same su3-file - the same set of RI, so m is subject to be monitored in I2P net grow. + + + +<h2>4. Go solution - Detailed Instructions</h2> + +<h3>1. Go solution - Overview</h3> <p> -Once or twice a week (or daily): pre-calculate ~100 new su3-files, each includes ~75 RI. -The RI are fetched from a well running I2P router's netdb directory. -Transfer the pre-calculate su3-files to your web server, e.g. by sftp or copy them locally to /var/www/su3/. -In the web server a PHP script will match one client IP to one of the 100 su3-files by hash+modulo. -This has the advantage to split su3-generation and publishing in web server . +The previous steps for reseeding involves many steps, scripts and programs. +Most of them are easy and plain straight forward, but overall you can call it a little confusing. <p> -Requirements for su3-file generation: -<ul> -<li>24/7 running i2p-router with up to date netdb -<li>ziptool, e.g. "zip" (Debian/Ubuntu: sudo apt-get install zip) -<li>Unix shell: find, awk, cat, ... -<li>your reseed keys: e.g. backup_at_mail.i2p.crt + keystore.ks + password -</ul> -Requirements for web server : +Here comes now an all-in-one solution from matt (Big Thanks!) for providing +a reseed server which merges the following functions into one binary: + <ul> -<li>PHP5 -<li>rewrite rule (*.su3 --> PHP) +<li>create su3-files +<li>create su3 signer certificate+key +<li>create ssl-certificate+key +<li>replaces the http-server and the PHP code (or run next to them in parallel) </ul> -The following solution for a public reseed server consists of three parts: +<p> +Almost all previous used scripts and described steps are not needed with this solution, +but to understand the overall reseed process it is recommended to read them too :-) + <ul> -<li>Unix shell script for cronjob -<li>PHP script -<li>url rewrite rule +<li>If you already have an ssl-certificate and su3-signer-key you can reuse them, see one of the following chapter. +<li>For testing and new reseeders the required certs and keys are created automatically at first start. +<li>Also take a look at the content and the naming scheme of these pem and crt files. </ul> -They are described on the following chapters in more detail. +<p> +Of course you need an up-to-date netDB folder with routerinfos from a running i2p router. +I2P does not have to be running on the same machine as this reseed binary. +In this case you can setup a cronjob to transfer the netDB from the I2P machine to the reseed machine. + +<p> +Matt's go solution can be used in parallel next to an already running http-server. +For this leave the http-server running at normal port 80 and 443, +and configure Go solution too use another port, e.g. port 8443. +<p> +More: at github, README.md, https://github.com/MDrollette/i2p-tools -<h3>7. Unix shell script for cronjob</h3> +<h3>2. Go solution - Building from source</h3> <p> -This script pre-calculates n su3-files. -Requirements: Unix shell, Java, I2P, zip-tool, your private reseed signing key -Main Steps: -<pre> -# CONFIG -# CHECK REQUIREMENT -# CREATE index files from netdB: use only 66% and max. 10h old -# CREATE zip files -# CREATE su3 files -# FINALIZE -</pre> -<p> -Please check and edit #CONFIG sections, please review code before use. -The resulting su3-files are placed in the "target" folder which can be changed in config section with "target". -Configure file permissions and file owner e.g. 'www-data' - see deactivated example lines. -The cronjob script runs ca. 10 seconds for generating 100 pre-calculated su3 files on a modern cpu. -The number of dat-files per su3 package is random. If you configure 75, it results in ca. 50...100 dat-files per su3-file. -The number of generated su3-files is random too, it depends on your netdb size and adapts automatically: +Requirements: <ul> -<li>1000 netdb entries: used for publishing: ~666, results in ~66 su3-files, each with ~75 dat-files -<li>3000 netdb entries: used for publishing: ~1999, results in ~199 su3-files, each with ~75 dat-files +<li>go1.4.2 (older versions may not work) </ul> -<p> -Only 66% of all RI from your netdb are used, netdb may be not older than 10h. -It is possible to separate cronjob script from PHP script: -Run the cronjob script on your I2P machine and then transfer the final su3-files via (s)ftp/ssh -to your web server from time to time. su3 file-size in this setup is between 50 and 100 KB per file. +<p> +Install go from https://golang.org/doc/install, example for 64 bit Ubuntu/Debian: +<ul> +<li>wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz +<li>sudo tar -C /usr/local -xzf go1.4.2.linux-amd64.tar.gz +<li>mkdir $HOME/go +<li>edit /etc/profile and add: +<pre> + export GOPATH=$HOME/go + export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin +</pre> +</ul> +<p> +Verify go: +<pre> +$ go version +</pre> +which should state something like: "go version go1.4.2" +<p> +Install Go solution from https://github.com/MDrollette/i2p-tools into $HOME/go: +<pre> +$ go get github.com/MDrollette/i2p-tools +</pre> -<h3>8. Setup cronjob</h3> +<p> +This will install a binary to $GOPATH/bin/i2p-tools <p> -Please add a cronjob, e.g. to run it every few days. -Add the shell script in crontab, e.g.: +Run the go solution, the usage/help should be displayed, nothing more: <pre> - crontab -e - 23 59 * * * /usr/local/bin/cronjob_i2p.sh +$ i2p-tools </pre> -<p> -The hard limit for the su3-file age is 30 days. -Recommendation is to update the su3-files once every 1..10 days. -<h3>9. PHP script for web server</h3> +<h3>3. Go solution - Run the reseed server</h3> -<p> -The su3.php script maps always one client IP to one pre-calculated su3-file. -Requirements: a web server with PHP5 -Main Steps: <pre> -# CONFIG -# HEALTH CHECK -# COUNT su3 files -# MAPPING Client IP to one SU3 -# PROVIDE SU3 +$ i2p-tools reseed --tlsHost=myserver.com --signer=myemail@mail.i2p --netdb=$HOME/.i2p/netDb </pre> -<p> -Please check and edit #CONFIG sections, please review code before use. -<p> -The date() function in the salt ensures a rotate once a day, even if su3-files are not updated daily. -To avoid scraping from attackers with big IPv4 subnet resources -(or even IPv6) some lower bytes of the client IP address are discarded: <ul> -<li>IPv4: 4 byte --> 1 lowest byte -<li>IPv6: 16 bytes --> 8 lowest bytes +<li>replace myserver.com with your real domain +<li>replace myemail@mail.i2p with a valid existing email, which you want to use for reseeding purpose +<li>new TLS certificate+key will be created (if they do not exist) +<li>new signing certificate+key will be created (if they do not exist) +<li>netdb=... should point to the netdb folder of your running I2P with the routerinfos +<li>to use another port append "--port=443" to the command, default is port 8443 </ul> -Clients in the same "subnet" gets the same su3-file <p> -A clients gets only different su3-file package in following circumstances: -<ul> -<li>when he gets a new IP (respecting the discarded bytes in the IPv4/v6 address) -<li>at 00:00 every date (date function in PHP) -<li>when the Unix cronjob updates the su3 files -</ul> +Output: +<pre> +2015/03/15 12:28:25 Rebuilding su3 cache... +2015/03/15 12:28:25 Building 200 su3 files each containing 75 out of 3180 routerInfos. +2015/03/15 12:28:35 Done rebuilding. +2015/03/15 12:28:35 HTTPS server started on 0.0.0.0:8443 +</pre> +<p> +So you can now test to reach the server at port 8443, see a previous chapter about proper testing. + +<p> +Some remarks: +<ul> +<li>don't run the server daemon as root +<li>every port between 1024 and 49151 is fine for I2P. +<li>if you want to use the privileged (https-default) port 443, create a port redirect, e.g. + iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 8443 +<li>redirect the output from the go solution to a logfile, format is default apache-style combined logs +<li>add a logrotate for the logfiles, since they grow big :-( +<li>logfiles can be used by fail2ban +<li>Both of the certificates (*.crt) will need to be sent to the reseed maintainer +in order for your reseed server to be included in the standard I2P package. +<li>Add a proper startup script, to run the reseed server, see next chapter +</ul> -<h3>10. url rewrite rule for web server</h3> +<h3>4. Go solution - Draft for startup script "seedserver"</h3> <p> -It is mandatory that clients does not have direct access to the su3-files at the web server. -Please activate a rewrite rule for su3-files in your web server pointing to the su3.php file: -<pre> - *.su3 --> su3.php?file=$1 -</pre> +The reseed server should be started automatically, so you need a init.d or some sort of +startscript, here named as "seedserver". +This is only a very first draft for a simple startscript (it could be done better :-)) +<p> +Login as I2P user: +<ul> +<li>place the shell-script "seedserver" in the /home/i2p/bin folder (next to i2p-tools) +<li>make it executable: chmod u+x /home/i2p/bin/seedserver +</ul> +Update the header "# Your settings" with your individual settings. <p> -Apache in ".htaccess": +Now you can use the shell-script: <pre> - Options +FollowSymlinks - RewriteEngine On - RewriteRule ^(.*\.su3)$ /su3.php?file=$1 [L] +seedserver start </pre> - <p> -lighttpd in "/etc/lighttpd/lighttpd.conf": +And then (give it some seconds) take a look at the status: <pre> - server.modules += ( "mod_rewrite" ) - url.rewrite-once = ( "^(.*\.su3)$" => "/su3.php?file=$1" ) +seedserver status +seedserver showlog </pre> <p> -We want only HTTPS accessible reseed server. -Sorted by best solution: +Some short explanation about seedserver: <ul> -<li>please deactivate plain HTTP, or -<li>use a redirect rule in your web server, or -<li>implement the redirect to HTTPS in the PHP code +<li>runs i2p-tools in the background +<li>creates logfiles +<li>take care of all settings </ul> - - -<h3>11. Create self-signed ssl-certificate</h3> - <p> -How-to generate a new self-signed ssl-certificate for HTTPS/TLS with openssl. -Example command line in Debian/Ubuntu for your.server.com: +If this is working fine, you can put the script in your personal crontab, to run it by auto-start +and to do logrotes simply by restarting it regularly once a week to avoid too big logfiles. +If you already reboot your server regularly, you can skip of course the "restart" command line. +<p> +Login as I2P user, edit your crontab: <pre> -$ openssl req -x509 -nodes -days 1500 -newkey rsa:4096 -sha256 -keyout your.server.com.pem -out your.server.com.pem -... -Country Name (2 letter code) [AU]:UK -State or Province Name (full name) [Some-State]:your.server.com -Locality Name (eg, city) []:your.server.com -Organization Name (eg, company) [Internet Widgits Pty Ltd]:your.server.com -Organizational Unit Name (eg, section) []:your.server.com -Common Name (e.g. server FQDN or YOUR name) []:your.server.com -Email Address []:your.server.com +crontab -e </pre> - <p> -The result is stored in "your.server.com.pem" file +and add these 3 lines at the end: +<pre> +@reboot /home/i2p/bin/seedserver startdelayed +04 14 * * 2 /home/i2p/bin/seedserver restart +#end +</pre> <p> -Remarks: -<ul> -<li>Please fill out all fields, don't use blanks -<li>rsa:4096 - key size, do not use 1024, you can use 2048 bits too, impact on server cpu -<li>use rsa, not ecdsa (ecdsa will break currently RetHat users) -<li>Optional: -Instead of RSA key and signature use a EC 384 key and signature, example: -<pre> -f=your.server.com -openssl ecparam -name secp384r1 -genkey -out $f.key -openssl req -new -x509 -key $f.key -out ${f}.crt -days 2000 -sha512 -cat $f.key $f.crt > $f.pem -</pre> -This results in a EC 384 bit key with SHA512withECDSA signature. -<li>days 1500 - validity period in days (choose at will between 1100-2000 (3-5 years)) -<li>sha256 - important, without this option openssl currently uses weak sha1 by default -<li>Do NOT reveal the private .pem key file to anyone - keep it save - keep a backup. -</ul> +Save and close the editor. It would be good to check if this is properly working when you reboot your machine. <p> -Next step: -<ul> -Open the created pem-file with a simple text editor. -You see the section with the private key and the section with the public key. -Copy the public section (starting with -----BEGIN CERTIFICATE-----) to another new file -and save the new file as your.server.com.crt file -</ul> +"seedserver" shell script: -<p> -Send this to us - the .crt file with the public key section will we included in every I2P router. -The .pem file with your private key is only for you and your web server. +<pre> +###################################################################################################### +#!/bin/sh + +# Your settings +toolpath=/home/i2p/bin +tlsHost=myserver.com +signer=myemail@mail.i2p +netdb="/home/i2p/.i2p/netDb" +tool=i2p-tools +logpath="$toolpath/${tool}.log" +logfile="$logpath/reseed.log" +errfile="$logpath/reseed.error" +cd "$toolpath" +mkdir --parents "$logpath" -<h3>12. Seamless ssl-certificate exchange</h3> -<p> -The update/exchange of an already existing self-signed certificates has to be correct timed -on server *and* client side. Considering thousands of clients (many with older I2P version) the exchange -will not be seamless possible and will have very bad impact on many clients: reseed won't work for them. +do_status() { +/bin/sleep 1 +if [ -n "$(pgrep -x "$tool")" ]; then +echo "$tool running, pid $(pgrep "$tool")" +else +echo "$tool not running." +fi; +} -<p> -To avoid this issue and make the exchange as smooth as possible follow these simple steps: +do_start() { +if [ -z "$(pgrep -x "$tool")" ]; then +do_logrotate +nohup "$toolpath/$tool" reseed -tlsHost="$tlsHost" --signer="$signer" --netdb="$netdb" > "$logfile" 2> "$errfile" & +fi; +do_status +} -<ol> -<li>generate a new ssl-certificate NOW, but do NOT implement it on server -<li>send the new ssl-certificate to us to perform a roll-out towards clients NOW -<li>WAIT some month, e.g. 3-4 i2p-releases -<li>new ssl-certificate is now hopefully present on many clients (in parallel to the current/old one) -<li>THEN exchange the ssl-certificate on server -</ol> +do_stop() { +if [ -n "$(pgrep -x "$tool")" ]; then +pkill "$tool" +fi; +do_status +} -<p> -This idea based on the fact, that you can provide in i2p/certificates/ssl more than one crt-file for a server, e.g. -server.com.crt and server.com2.crt +do_startdelayed() { +echo "waiting 20s..." +/bin/sleep 20 +do_start +} + +do_restart() { +do_status +do_stop +do_start +} +do_logrotate() { +do_status +if [ -z "$(pgrep -x "$tool")" ]; then +mv --force "${logfile}.6" "${logfile}.7" 2>/dev/null +mv --force "${logfile}.5" "${logfile}.6" 2>/dev/null +mv --force "${logfile}.4" "${logfile}.5" 2>/dev/null +mv --force "${logfile}.3" "${logfile}.4" 2>/dev/null +mv --force "${logfile}.2" "${logfile}.3" 2>/dev/null +mv --force "${logfile}.1" "${logfile}.2" 2>/dev/null +mv --force "${logfile}" "${logfile}.1" 2>/dev/null +mv --force "${errfile}.6" "${errfile}.7" 2>/dev/null +mv --force "${errfile}.5" "${errfile}.6" 2>/dev/null +mv --force "${errfile}.4" "${errfile}.5" 2>/dev/null +mv --force "${errfile}.3" "${errfile}.4" 2>/dev/null +mv --force "${errfile}.2" "${errfile}.3" 2>/dev/null +mv --force "${errfile}.1" "${errfile}.2" 2>/dev/null +mv --force "${errfile}" "${errfile}.1" 2>/dev/null +echo "log-rotate done." +else +echo "log-rotate not possible." +fi; +} +do_showlog() { +echo "-------------------------------------------------------------------------------" +tail "$errfile" +echo "-------------------------------------------------------------------------------" +tail "$logfile" +echo "-------------------------------------------------------------------------------" +} -<h3>13. reseed server domain/url/port exchange</h3> +do_usage() { +echo "Usage: {start|stop|status|restart|logrotate|startdelayed|showlog}" +} +case "$1" in +start) +do_start +;; +stop) +do_stop +;; +status) +do_status +;; +restart) +do_restart +;; +startdelayed) +do_startdelayed +;; +logrotate) +do_logrotate +;; +showlog) +do_showlog +;; +*) +do_usage +;; +esac -<p> -You are already operating a reseed server but want to change your domain/url/port? -To make the exchange as smooth as possible for many clients please follow these steps if possible: +exit 0 +###################################################################################################### +</pre> -<ol> -<li>Setup an additional reseed instance at the new domain/url/port -<li>we include the new url into I2P source NOW and delete the old url NOW -<li>both of your reseed instances have to run some time in parallel -<li>WAIT some month, e.g. 3-4 i2p-releases -<li>new url is now hopefully present on many clients -<li>THEN shutdown the old reseed instance -</ol> -<h3>14. Tests</h3> +<h3>5. Go solution - reverse-proxy setup</h3> <p> -Some simple pre-test: test the website and fetch +You can run i2p-tools also behind your normal web-server (reverse-proxy). + +<p> +The web-server handles the TLS handshake, encryption, SSL Certificate and the logfiles. +But you don't need the scripts su3.php and the shell cronjob for creating su3-files. +i2p-tools is running "behind" the web-server, without TLS management, only bind to +local interface 127.0.0.1 and is handling complete building and handling of su3-files. + + +<p> +Run i2p-tools with this command: + <pre> - wget --user-agent="Wget/1.11.4" -O /tmp/test.su3 --no-check-certificate https://your-server.com:PORT/i2pseeds.su3 +i2p-tools reseed --signer test@test.de --key /path_to/test_at_test.de.pem --netdb /path_to/netDb --port=8443 --ip 127.0.0.1 --trustProxy </pre> -Replace "PORT" with default 443 or your chosen server setting. -Inspect the fetched file.: -Some simple pre-test: test the website and fetch + +Important notes for this special setup: +<ul> +<li>do *not* specify --tlsHost, --tlsCert or --tlsKey on the command-line +<li>"ip 127.0.0.1" binds the program only to local interface +<li>"trustProxy" uses the "X-Forwarded-For" to get the real client IP +</ul> + +"trustProxy" uses the "X-Forwarded-For" to get the real client IP + + +<p> +lighttpd configuration example: <pre> - zipinfo -z /tmp/test.su3 + server.modules += ( "mod_proxy" ) + proxy.server = ( ".su3" => ( ( "host" => "127.0.0.1", "port" => 8443 ) ) ) </pre> -<p> -Replace "--no-check-certificate" with "--ca-certificate=~/i2p/certificates/ssl/your-server.com.crt" -which contains the path to your local public ssl-certificate to check also your ssl-certificate chain. <p> -Everything ok: -<ul> -<li>ssl-certificate chain valid? -<li>The su3-files can be downloaded? -<li>contains > 50 dat-files? -<li>and is always the same for one client-IP? -<li>other client-IP's gets another file? -<li>Clients has no direct access to complete folder e.g. https://your-server.com/su3/ ? -</ul> +nginx configuration example: +<pre> + location / { + proxy_pass http://127.0.0.1:8443; + } +</pre> <p> -Do a real reseed test on *another* I2P router machine: -<ul> -<li>include manually new ssl-certificate into i2p installation: ~/i2p/certificates/ssl/ -<li>include manually new public reseed key into i2p installation: ~/i2p/certificates/reseed/ -<li>http://localhost:7657/configreseed --> remove all reseed hosts -<li>add the new reseed host e.g. "https://your-server.com/" *without* trailing "i2pseeds.su3" -<li>Save and Shutdown router. -<li>clear netdb: empty folder ./i2p/netDb. -<li>Restart I2P and watch the I2P router log: +and for X-Forwarded-For: <pre> -2014/10/13 23:01:02 | Reseed start -2014/10/13 23:01:02 | Reseeding from https://your-server/i2pseeds.su3 -2014/10/13 23:01:05 | INFO: xx files extracted to /tmp/i2p-V2qudTbd.tmp/reseeds-1010682701 -2014/10/13 23:01:05 | Reseed got xx router infos from https://your-server.com/i2pseeds.su3 with 0 errors -2014/10/13 23:01:06 | Reseed complete, xx received + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; </pre> -</ul> -<h3>15. Contact reseed maintainer</h3> +<h3>6. Go solution - Convert existing Java keystore to crt- and pem-file</h3> <p> -Contact us per email backup@mail.i2p (fallback is killyourtv@mail.i2p or the reseed section at zzz's forum) -Provide us details about the new +This describes how to convert your existing Java keystore with your su3 signing key to a plain crt- and pem-file. +This is only needed, when you already have a Java keystore and want to use Go solution. +If you create new keys+certs with matt's solution you can skip this chapter! + +<p> +Requirements: <ul> -<li>reseed website url, -<li>public part of ssl-certificate -<li>public su3-key -<li>your contact email +<li>Java keytool +<li>openssl +<li>and of course your secret password for the keystore </ul> -<p> -Feel free to contact backup@mail.i2p in case of questions or problems or post your question at zzz's forum in the reseed section. - +<p> +Keep in mind: the Java keystore has two passwords: +<ul> +<li>the secret key password you have entered while creating your keystore the first time (SU3File keygen ...) +<li>and a "storage" password, which is most probably default "changeit". +</ul> +<p> +This works in a Ubuntu/Debian shell: -<h3>16. Script - cronjob_i2p.sh</h3> <pre> -############################################################################### -#!/bin/sh -version="v5" - - -# CONFIG -I2P="${HOME}/i2p" # i2p installation directory -source="${HOME}/.i2p/netDb" # valid netdb -target="${HOME}/i2pseeds.su3" # location for the final su3-files +###################################################################################################### +file="keystore.ks" +pass_jks=changeit -key_keystore="${I2P}/keystore.ks" # your private su3 reseed key -key_password="secret" # your password for private key of keystore.ks -key_email=yourmail@mail.i2p # your email id for reseeding -key_type=RSA_SHA512_4096 # your key size/type for reseeding (DO NOT EDIT, unless you know why) +# List the keystore content, show the included (email) alias +keytool -list -storepass $pass_jks -keystore $file -tool_zip="/usr/bin/zip" # install a "zip" tool: sudo apt-get install zip -tool_i2p="$I2P/lib/i2p.jar" # should be already there +# Convert jks --> pkcs12, specify the correct email alias (xxxxx@mail.i2p): +keytool -importkeystore -srcalias xxxxx@mail.i2p -srckeystore $file -srcstoretype jks -srcstorepass $pass_jks -destkeystore ${file}.p12 -deststoretype pkcs12 -deststorepass $pass_jks -destkeypass $pass_jks +# Show the pkcs12 content: +openssl pkcs12 -passin pass:$pass_jks -in ${file}.p12 -nodes -info -# CONFIG (DO NOT EDIT) -ri_seed=75 # average number ri per su3-file (DO NOT EDIT) -stamp=$(date +%s) # unique id (DO NOT EDIT) -target_tmp="/tmp/i2pseeds.${stamp}.tmp" # temp folder with unique id (DO NOT EDIT) +# Convert pkcs12 --> pem +openssl pkcs12 -passin pass:$pass_jks -in ${file}.p12 -nodes -out ${file}.pem +# Decrypt the pem +openssl rsa -in ${file}.pem -out xxxxx_at_mail.i2p.pem -# CLEAN /tmp/i2pseeds.* -find /tmp -type d -iname 'i2pseeds.*.tmp' -exec rm -rf {} \; -mkdir --parents "${target_tmp}" +# Extract the certificate +openssl x509 -in ${file}.pem -out xxxxx_at_mail.i2p.crt +###################################################################################################### +</pre> -# CHECK REQUIREMENT -[ ! -d "${I2P}" ] && echo "ERROR1: path not found: ${I2P}" && exit 1 -[ ! -d "${source}" ] && echo "ERROR2: path not found: ${source}" && exit 1 -[ ! -d "${target_tmp}" ] && echo "ERROR3: path not found: ${target_tmp}" && exit 1 -[ ! -x "${tool_zip}" ] && echo "ERROR4: command not found: ${tool_zip}" && exit 1 -[ ! -f "${tool_i2p}" ] && echo "ERROR5: file not found: ${tool_i2p}" && exit 1 -[ ! -f "${key_keystore}" ] && echo "ERROR6: file not found: ${key_keystore}" && exit 1 -# CREATE index-files from netdB: use only 66% and max. 10h old -find "${source}" -type f -mmin -600 -name 'routerInfo-*.dat' | awk -v ri_seed="${ri_seed}" -v target_tmp="${target_tmp}" ' - BEGIN { ri_all=0; } - { data[ri_all++]=$0; } - END { srand(); - ri_use=ri_all*0.6666; - ri_su3=int(ri_use/10); - stepy=ri_use/ri_all; - stepx=ri_seed/ri_use; - for (y=0;y<ri_all; y++) if (rand()<=stepy) { - for (x=0; x<ri_su3; x++) if (rand()<=stepx) { - file=target_tmp"/"x".index"; - print data[y] >> file - } - } - }' +<h2>5. PHP solution - Not recommended</h2> -# CREATE zip-files from index-files -find "${target_tmp}" -type f -name '*.index' | sort | while read i; do - "${tool_zip}" --update --quiet --junk-paths "${target_tmp}/$(basename "$i" .index)" -@ < "$i" -done +<h3>1. Short overview</h3> +<ul> +<li>permanent: run your I2P router +<li>once: generate a private and public key pair for signing the reseed files +<li>once: setup the PHP script on the web server +<li>once: setup a rewrite rule at web server (*.su3 --> su3.php) +<li>regularly: run the Unix shell script to generate up-to-date su3-files +<li>regularly: transfer su3-files to local /var/www/ or with (s)ftp to your remote web server +</ul> -# CREATE su3-files from zip-files -echo "${key_password}" | java -cp "${tool_i2p}" net.i2p.crypto.SU3File bulksign -c RESEED -t "${key_type}" "${target_tmp}" "${key_keystore}" "${stamp}" "${key_email}" -# REMOVE index-files and zip-files -find "${target_tmp}" -type f -name '*.index' -exec rm -f "{}" \; -find "${target_tmp}" -type f -name '*.zip' -exec rm -f "{}" \; +<h3>2. su3-file guidelines for reseeding</h3> +<p> +(From <a href="http://zzz.i2p/topics/1648">zzz.i2p</a>) +<ul> +<li>The su3-file must be named "i2pseeds.su3" +<li>The file must be in the same directory as the routerinfos on the web server +<li>Router will first try to fetch (index url)/i2pseeds.su3; + if that fails it will fetch (index url) and then fetch the individual RI files, old-style +<li>Once a reseed from a host succeeds, it won't try any other URLs from that host + (either http or https, ignoring ports... ports are now implemented) +<li>RI files in the zip file (in the su3-file) must be at the "top level", + i.e. no directories in the zip file +<li>su3 content type must be RESEED (-c 3 or -c RESEED) +<li>su3 signature type should be RSA 4096 (-t 6 or -t RSA_SHA512_4096). + If you're very low on CPU power you could use a shorter key, but you only need to do the signing process once a day or so. + Any sig type will work, but RSA 4096 is the best in this case. +<li>Of course we must have your su3 signing public key checked in + under the same name as you are using in the signing process, + e.g. for you@mail.i2p the file name must be you_at_mail.i2p.crt, in the certificates/reseed/ directory +</ul> -# FINAL CHECK number su3-files -c_su3=$(find "${target_tmp}" -type f -mmin -600 -name '*.su3' | wc -l) -[ "${c_su3}" -lt 25 ] && echo "ERROR7: less than 25 su3 files found: ${c_su3}" && rm -Rf "${target_tmp}" && exit 1 -echo "Created: $target_tmp ${c_su3} x${ri_seed}" -# MOVE su3-files to target -chmod 755 "${target_tmp}" -R -rm -fr "${target}.old" -mv -f "${target}" "${target}.old" -mv -f "${target_tmp}" "${target}" -rm -fr "${target_tmp}" +<h3>3. How to prepare your key pair for su3-files</h3> +<p> +( from <a href="http://zzz.i2p/topics/1643">zzz.i2p</a>) +<ul> +<li>Details are posted here from zzz: <a href="http://zzz.i2p/topics/1473">zzz.i2p</a> +<li>Who? All owner of a public reseed server. +<li>Why? su3 reseed files will be signed with your private key. +<li>This ensures a secure bootstrap for I2P routers. +<li>Corresponding public keys will be included in I2P router package. +</ul> -# EXIT -echo "$(basename "$0")" "${version} ${target} ${c_su3} x${ri_seed}" -logger -t "$(basename "$0")" "${version} ${target} ${c_su3} x${ri_seed}" -exit 0 -############################################################################### +<p> +Example to create your key pair: +<pre> + su - i2puser + I2P=/home/i2puser/i2p + cd $I2P + java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File keygen -t RSA_SHA512_4096 backup_at_mail.i2p.crt keystore.ks backup@mail.i2p </pre> +<p> +Short usage help: +<pre> + SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p +</pre> +<p> +Get more help: +<pre> + java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File +</pre> +<p> +Provide a strong password for your private key. +In this example two new files will be created in the working folder: +<ul> +<li>backup_at_mail.i2p.crt will contain the public key +<li>keystore.ks is the Java keystore file and contains your private key +</ul> +<p> +Backup and store public key, private key and your password! +Remember also the used key size/type when not using default RSA_SHA512_4096. +Send the public .crt key file to us, to include it into i2p/certificates/reseed/ +If you have mtn privs, you may check the (you)_at_mail.i2p.crt file directly into installer/resources/certificates/reseed . +The file name must be (email address used for signing).crt, with "@" replaced with "_at_". +There is no requirement that it be xxx@mail.i2p, any email is fine, or for that matter any identifier. -<h3>17. Script - su3.php</h3> -<pre> -############################################################################### -<?php -$version="v5"; - -# CONFIG -$path_su3="/home/i2p/i2pseeds.su3"; # path to pre-calculated su3 files -$salt="change_to_something"; # change salt to something random -$salt=$salt . date("Y-m-d"); # date() ensures a rotate once a day, even if su3 are not updated daily (DO NOT EDIT) -$file_su3 = "i2pseeds.su3"; # static (DO NOT EDIT) -$user_agent= "Wget/1.11.4"; # static (DO NOT EDIT) +<h3>4. su3 server-side implementation</h3> + +<p> +(from <a href="http://zzz.i2p/topics/1647">zzz.i2p</a>) +This describes a mechanism for creating and distributing the RI in new su3 format. +It's independent from legacy way of doing (fetching dat-files) and can be used in parallel. +This idea doesn't need mysql, only some Unix shell tools and a simple web server with PHP works fine. +<p> +A requesting client gets ~75 RI packed into one zip, signed and converted to a su3-file. +Don't provide unlimited RI to one clients. +But don't try to keep track of million client IP's in a database, e.g think of ipv6. +Keep it simple: make a fix n:m one-direction matching: n*ip --> m*su3-file by modulo. +n is the unlimited IPv4+IPv6 address space, and m are e.g. 100 pre-calculated su3-files. +A client with one IP gets always the same su3-file, until the su3-file is updated or the client has a new IP. +A number of clients (n/m ratio) gets the same su3-file - the same set of RI, so m is subject to be monitored in I2P net grow. -# INSIDE i2p-net ? If yes: convert DESTB32 into pseudo IPv6 as valid REMOTE_ADDR -if ( $_SERVER["REMOTE_ADDR"]=="127.0.0.1" - && isset($_SERVER["HTTP_X_I2P_DESTB32"]) - ) { $_SERVER["REMOTE_ADDR"]=inet_ntop(substr(md5($_SERVER["HTTP_X_I2P_DESTB32"]),0,16)); } +<p> +Once or twice a week (or daily): pre-calculate ~100 new su3-files, each includes ~75 RI. +The RI are fetched from a well running I2P router's netdb directory. +Transfer the pre-calculate su3-files to your web server, e.g. by sftp or copy them locally to /var/www/su3/. +In the web server a PHP script will match one client IP to one of the 100 su3-files by hash+modulo. +This has the advantage to split su3-generation and publishing in web server . +<p> +Requirements for su3-file generation: +<ul> +<li>24/7 running i2p-router with up to date netdb +<li>ziptool, e.g. "zip" (Debian/Ubuntu: sudo apt-get install zip) +<li>Unix shell: find, awk, cat, ... +<li>your reseed keys: e.g. backup_at_mail.i2p.crt + keystore.ks + password +</ul> +Requirements for web server : +<ul> +<li>PHP5 +<li>rewrite rule (*.su3 --> PHP) +</ul> -# HEALTH CHECK 1 -if ( !isset($_SERVER['HTTP_USER_AGENT']) - || !isset($_SERVER['REMOTE_ADDR']) - || !isset($_GET['file']) - ) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } +The following solution for a public reseed server consists of three parts: +<ul> +<li>Unix shell script for cronjob +<li>PHP script +<li>url rewrite rule +</ul> +They are described on the following chapters in more detail. -# COUNT su3 files -$count_su3 = count(glob($path_su3."/*.su3")); -# HEALTH CHECK 2 -if ( empty($_SERVER['HTTP_USER_AGENT']) - || empty($_SERVER['REMOTE_ADDR']) - || empty($_GET['file']) - || (strcmp(basename($_GET['file']), $file_su3) != 0) - || (strcmp($_SERVER['HTTP_USER_AGENT'], $user_agent) != 0) - || !filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) - || $count_su3<1 - ) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } +<h3>5. Unix shell script for cronjob</h3> +<p> +This script pre-calculates n su3-files. +Requirements: Unix shell, Java, I2P, zip-tool, your private reseed signing key +Main Steps: +<pre> +# CONFIG +# CHECK REQUIREMENT +# CREATE index files from netdB: use only 66% and max. 10h old +# CREATE zip files +# CREATE su3 files +# FINALIZE +</pre> +<p> +Please check and edit #CONFIG sections, please review code before use. +The resulting su3-files are placed in the "target" folder which can be changed in config section with "target". +Configure file permissions and file owner e.g. 'www-data' - see deactivated example lines. +The cronjob script runs ca. 10 seconds for generating 100 pre-calculated su3 files on a modern cpu. +The number of dat-files per su3 package is random. If you configure 75, it results in ca. 50...100 dat-files per su3-file. +The number of generated su3-files is random too, it depends on your netdb size and adapts automatically: +<ul> +<li>1000 netdb entries: used for publishing: ~666, results in ~66 su3-files, each with ~75 dat-files +<li>3000 netdb entries: used for publishing: ~1999, results in ~199 su3-files, each with ~75 dat-files +</ul> +<p> +Only 66% of all RI from your netdb are used, netdb may be not older than 10h. +It is possible to separate cronjob script from PHP script: +Run the cronjob script on your I2P machine and then transfer the final su3-files via (s)ftp/ssh +to your web server from time to time. su3 file-size in this setup is between 50 and 100 KB per file. -# MAPPING Client IP to one su3-file -$remote_id = inet_pton($_SERVER['REMOTE_ADDR']); -$shrink=3; if (strlen($remote_id)>8) { $shrink=8; }; -$remote_id = abs(crc32(md5(substr($remote_id,0,$shrink).$salt))) % $count_su3; -$file_id = $path_su3."/".$remote_id.".su3"; -# HEALTH CHECK 3 -if (!file_exists($file_id)) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } +<h3>6. Setup cronjob</h3> -# PROVIDE su3-file -header('Content-Description: File Transfer'); -header("Content-Type: application/zip"); -header('Content-Transfer-Encoding: binary'); -header('Content-Length: '.filesize($file_id)); -header('Content-Disposition: attachment; filename='.$file_su3); -ob_clean(); flush(); -if (!readfile($file_id)) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } -exit; -?> -############################################################################### +<p> +Please add a cronjob, e.g. to run it every few days. +Add the shell script in crontab, e.g.: +<pre> + crontab -e + 23 59 * * * /usr/local/bin/cronjob_i2p.sh </pre> +<p> +The hard limit for the su3-file age is 30 days. +Recommendation is to update the su3-files once every 1..10 days. -<h3>18. Optional - setup a manual reseed method</h3> -<p> -For some users the automated reseeding may not work. -This is an alternate way for users to get a valid reseed file with a normal web-browser, -e.g. from another machine or maybe a friend. It is secured by a captcha to prevent abuse. -<p> -With this optional code users can visit https://your.reseedserver.com/reseed.php -with any web-browser to download a su3-file after they solved the captcha. +<h3>7. PHP script for web server</h3> <p> -Since 0.9.18-9 I2P has support to use reseed files from other sources: -http://localhost:7657/configreseed - +The su3.php script maps always one client IP to one pre-calculated su3-file. +Requirements: a web server with PHP5 +Main Steps: +<pre> +# CONFIG +# HEALTH CHECK +# COUNT su3 files +# MAPPING Client IP to one SU3 +# PROVIDE SU3 +</pre> <p> -Visit https://geti2p.net/en/faq#manual_reseed to read how it works for users and see some example url's. -[NOT DONE YET: read here: <a href="http://zzz.i2p/topics/1828-running-prototype-manually-reseed-captcha">zzz.i2p</a> -or test here anonymously: <a href="http://reseed.i2p/open.php">reseed.i2p</a>] +Please check and edit #CONFIG sections, please review code before use. <p> -The changes for an exiting reseed server with the previous setup are simple: +The date() function in the salt ensures a rotate once a day, even if su3-files are not updated daily. +To avoid scraping from attackers with big IPv4 subnet resources +(or even IPv6) some lower bytes of the client IP address are discarded: <ul> -<li>use the latest su3.php from above (minimal version 5, only minor changes, no change of logic). -<li>add the new reseed.php to your /var/www folder, next to to su3.php -<li>install php5-gd (restart of PHP processes may be necessary) -<li>get Securimage php-code from https://www.phpcaptcha.org/ +<li>IPv4: 4 byte --> 1 lowest byte +<li>IPv6: 16 bytes --> 8 lowest bytes </ul> +Clients in the same "subnet" gets the same su3-file <p> -Quote from https://www.phpcaptcha.org (2015-03): -"Securimage is an open-source free PHP CAPTCHA script for generating complex images and CAPTCHA codes to protect -forms from spam and abuse. It can be easily added into existing forms on your website to provide protection from spam bots. -It can run on most any web server as long as you have PHP installed, and GD support within PHP. -Securimage does everything from generating the CAPTCHA images to validating the typed code." +A clients gets only different su3-file package in following circumstances: +<ul> +<li>when he gets a new IP (respecting the discarded bytes in the IPv4/v6 address) +<li>at 00:00 every date (date function in PHP) +<li>when the Unix cronjob updates the su3 files +</ul> + -<p> -Short overview about installing Securimage: -<ol> -<li>download at https://www.phpcaptcha.org/download/ -<li>extract to /var/www/securimage -<li>download and extract the "Test Script" (securimage_test.php) from the same url -<li>test your server and visit https://.../securimage_test.php with your browser -</ol> -<p> -The "Test Script" verifies your ability to run and display the captcha code, and can be deleted after the test. -<p> -The reseed.php contains only the captcha generation and verification of the users input. It is based on the -Quickstart Guide from Securimage. When the user solved the captcha, reseed.php sets two http variables and -then includes the external su3.php to start the su3-file download. -<p> -The name "reseed.php" is not fixed, you can name it unremarkable/unobtrusive as you like, -enter.php start.php go.php... -but you have to stick with it, when it is published :-) + +<h3>8. url rewrite rule for web server</h3> <p> -reseed.php: +It is mandatory that clients does not have direct access to the su3-files at the web server. +Please activate a rewrite rule for su3-files in your web server pointing to the su3.php file: <pre> -################################################################################################ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body> -<?php -session_start(); -include_once $_SERVER['DOCUMENT_ROOT'] . '/securimage/securimage.php'; -$securimage = new Securimage(); - -if (!isset($_POST['captcha_code']) || $securimage->check($_POST['captcha_code']) == false) {?> - <form method="post" action="<?php echo(basename($_SERVER['PHP_SELF'])); ?>"> - <img id="captcha" src="/securimage/securimage_show.php" alt="CAPTCHA Image" /> - <p>Enter Code: <input type="text" name="captcha_code" size="10" maxlength="6" /> - <input type="submit" value="Check Code" /> - </form> -<?php } else { - $_SERVER['HTTP_USER_AGENT']="Wget/1.11.4"; - $_GET['file']="i2pseeds.su3"; - include_once $_SERVER['DOCUMENT_ROOT'] . "/su3.php"; -} ?> -</body></html> -################################################################################################ + *.su3 --> su3.php?file=$1 </pre> - - -<h3>19. matt's go solution - Overview</h3> - <p> -The previous steps for reseeding involves many steps, scripts and programs. -Most of them are easy and plain straight forward, but overall you can call it a little confusing. +Apache in ".htaccess": +<pre> + Options +FollowSymlinks + RewriteEngine On + RewriteRule ^(.*\.su3)$ /su3.php?file=$1 [L] +</pre> <p> -Here comes now an all-in-one solution from matt (Big Thanks!) for providing -a reseed server which merges the following functions into one binary: - -<ul> -<li>create su3-files -<li>create su3 signer certificate+key -<li>create ssl-certificate+key -<li>replaces the http-server and the PHP code (or run next to them in parallel) -</ul> +lighttpd in "/etc/lighttpd/lighttpd.conf": +<pre> + server.modules += ( "mod_rewrite" ) + url.rewrite-once = ( "^(.*\.su3)$" => "/su3.php?file=$1" ) +</pre> <p> -Almost all previous used scripts and described steps are not needed with this solution, -but to understand the overall reseed process it is recommended to read them too :-) - +We want only HTTPS accessible reseed server. +Sorted by best solution: <ul> -<li>If you already have an ssl-certificate and su3-signer-key you can reuse them, see one of the following chapter. -<li>For testing and new reseeders the required certs and keys are created automatically at first start. -<li>Also take a look at the content and the naming scheme of these pem and crt files. +<li>please deactivate plain HTTP, or +<li>use a redirect rule in your web server, or +<li>implement the redirect to HTTPS in the PHP code </ul> -<p> -Of course you need an up-to-date netDB folder with routerinfos from a running i2p router. -I2P does not have to be running on the same machine as this reseed binary. -In this case you can setup a cronjob to transfer the netDB from the I2P machine to the reseed machine. - -<p> -Matt's go solution can be used in parallel next to an already running http-server. -For this leave the http-server running at normal port 80 and 443, -and configure matt's go solution too use another port, e.g. port 8443. - -<p> -More: at github, README.md, https://github.com/MDrollette/i2p-tools -<h3>20. matt's go solution - Building from source</h3> +<h3>9. Create self-signed ssl-certificate</h3> <p> -Requirements: -<ul> -<li>go1.4.2 (older versions may not work) -</ul> +How-to generate a new self-signed ssl-certificate for HTTPS/TLS with openssl. +Example command line in Debian/Ubuntu for your.server.com: -<p> -Install go from https://golang.org/doc/install, example for 64 bit Ubuntu/Debian: -<ul> -<li>wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz -<li>sudo tar -C /usr/local -xzf go1.4.2.linux-amd64.tar.gz -<li>mkdir $HOME/go -<li>edit /etc/profile and add: <pre> - export GOPATH=$HOME/go - export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin +$ openssl req -x509 -nodes -days 1500 -newkey rsa:4096 -sha256 -keyout your.server.com.pem -out your.server.com.pem +... +Country Name (2 letter code) [AU]:UK +State or Province Name (full name) [Some-State]:your.server.com +Locality Name (eg, city) []:your.server.com +Organization Name (eg, company) [Internet Widgits Pty Ltd]:your.server.com +Organizational Unit Name (eg, section) []:your.server.com +Common Name (e.g. server FQDN or YOUR name) []:your.server.com +Email Address []:your.server.com </pre> -</ul> <p> -Verify go: -<pre> -$ go version -</pre> -which should state something like: "go version go1.4.2" +The result is stored in "your.server.com.pem" file <p> -Install matt's go solution from https://github.com/MDrollette/i2p-tools into $HOME/go: -<pre> -$ go get github.com/MDrollette/i2p-tools -</pre> +Remarks: +<ul> +<li>Please fill out all fields, don't use blanks +<li>rsa:4096 - key size, do not use 1024, you can use 2048 bits too, impact on server cpu +<li>use rsa, not ecdsa (ecdsa will break currently RetHat users) +<li>Optional: +Instead of RSA key and signature use a EC 384 key and signature, example: +<pre> +f=your.server.com +openssl ecparam -name secp384r1 -genkey -out $f.key +openssl req -new -x509 -key $f.key -out ${f}.crt -days 2000 -sha512 +cat $f.key $f.crt > $f.pem +</pre> +This results in a EC 384 bit key with SHA512withECDSA signature. +<li>days 1500 - validity period in days (choose at will between 1100-2000 (3-5 years)) +<li>sha256 - important, without this option openssl currently uses weak sha1 by default +<li>Do NOT reveal the private .pem key file to anyone - keep it save - keep a backup. +</ul> <p> -This will install a binary to $GOPATH/bin/i2p-tools +Next step: +<ul> +Open the created pem-file with a simple text editor. +You see the section with the private key and the section with the public key. +Copy the public section (starting with -----BEGIN CERTIFICATE-----) to another new file +and save the new file as your.server.com.crt file +</ul> <p> -Run the go solution, the usage/help should be displayed, nothing more: -<pre> -$ i2p-tools -</pre> - - +Send this to us - the .crt file with the public key section will we included in every I2P router. +The .pem file with your private key is only for you and your web server. -<h3>21. matt's go solution - Run the reseed server</h3> -<pre> -$ i2p-tools reseed --tlsHost=myserver.com --signer=myemail@mail.i2p --netdb=$HOME/.i2p/netDb -</pre> -<ul> -<li>replace myserver.com with your real domain -<li>replace myemail@mail.i2p with a valid existing email, which you want to use for reseeding purpose -<li>new TLS certificate+key will be created (if they do not exist) -<li>new signing certificate+key will be created (if they do not exist) -<li>netdb=... should point to the netdb folder of your running I2P with the routerinfos -<li>to use another port append "--port=443" to the command, default is port 8443 -</ul> +<h3>10. Seamless ssl-certificate exchange</h3> <p> -Output: -<pre> -2015/03/15 12:28:25 Rebuilding su3 cache... -2015/03/15 12:28:25 Building 200 su3 files each containing 75 out of 3180 routerInfos. -2015/03/15 12:28:35 Done rebuilding. -2015/03/15 12:28:35 HTTPS server started on 0.0.0.0:8443 -</pre> +The update/exchange of an already existing self-signed certificates has to be correct timed +on server *and* client side. Considering thousands of clients (many with older I2P version) the exchange +will not be seamless possible and will have very bad impact on many clients: reseed won't work for them. <p> -So you can now test to reach the server at port 8443, see a previous chapter about proper testing. +To avoid this issue and make the exchange as smooth as possible follow these simple steps: + +<ol> +<li>generate a new ssl-certificate NOW, but do NOT implement it on server +<li>send the new ssl-certificate to us to perform a roll-out towards clients NOW +<li>WAIT some month, e.g. 3-4 i2p-releases +<li>new ssl-certificate is now hopefully present on many clients (in parallel to the current/old one) +<li>THEN exchange the ssl-certificate on server +</ol> <p> -Some remarks: -<ul> -<li>don't run the server daemon as root -<li>every port between 1024 and 49151 is fine for I2P. -<li>if you want to use the privileged (https-default) port 443, create a port redirect, e.g. - iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 8443 -<li>redirect the output from the go solution to a logfile, format is default apache-style combined logs -<li>add a logrotate for the logfiles, since they grow big :-( -<li>logfiles can be used by fail2ban -<li>Both of the certificates (*.crt) will need to be sent to the reseed maintainer -in order for your reseed server to be included in the standard I2P package. -<li>Add a proper startup script, to run the reseed server, see next chapter -</ul> +This idea based on the fact, that you can provide in i2p/certificates/ssl more than one crt-file for a server, e.g. +server.com.crt and server.com2.crt -<h3>22. matt's go solution - Draft for startup script "seedserver"</h3> +<h3>11. reseed server domain/url/port exchange</h3> + <p> -The reseed server should be started automatically, so you need a init.d or some sort of -startscript, here named as "seedserver". -This is only a very first draft for a simple startscript (it could be done better :-)) -<p> -Login as I2P user: -<ul> -<li>place the shell-script "seedserver" in the /home/i2p/bin folder (next to i2p-tools) -<li>make it executable: chmod u+x /home/i2p/bin/seedserver -</ul> -Update the header "# Your settings" with your individual settings. +You are already operating a reseed server but want to change your domain/url/port? +To make the exchange as smooth as possible for many clients please follow these steps if possible: + +<ol> +<li>Setup an additional reseed instance at the new domain/url/port +<li>we include the new url into I2P source NOW and delete the old url NOW +<li>both of your reseed instances have to run some time in parallel +<li>WAIT some month, e.g. 3-4 i2p-releases +<li>new url is now hopefully present on many clients +<li>THEN shutdown the old reseed instance +</ol> + + + +<h3>12. Tests</h3> <p> -Now you can use the shell-script: +Some simple pre-test: test the website and fetch <pre> -seedserver start + wget --user-agent="Wget/1.11.4" -O /tmp/test.su3 --no-check-certificate https://your-server.com:PORT/i2pseeds.su3 </pre> -<p> -And then (give it some seconds) take a look at the status: +Replace "PORT" with default 443 or your chosen server setting. +Inspect the fetched file.: +Some simple pre-test: test the website and fetch <pre> -seedserver status -seedserver showlog + zipinfo -z /tmp/test.su3 </pre> <p> -Some short explanation about seedserver: -<ul> -<li>runs i2p-tools in the background -<li>creates logfiles -<li>take care of all settings -</ul> +Replace "--no-check-certificate" with "--ca-certificate=~/i2p/certificates/ssl/your-server.com.crt" +which contains the path to your local public ssl-certificate to check also your ssl-certificate chain. <p> -If this is working fine, you can put the script in your personal crontab, to run it by auto-start -and to do logrotes simply by restarting it regularly once a week to avoid too big logfiles. -If you already reboot your server regularly, you can skip of course the "restart" command line. +Everything ok: +<ul> +<li>ssl-certificate chain valid? +<li>The su3-files can be downloaded? +<li>contains > 50 dat-files? +<li>and is always the same for one client-IP? +<li>other client-IP's gets another file? +<li>Clients has no direct access to complete folder e.g. https://your-server.com/su3/ ? +</ul> <p> -Login as I2P user, edit your crontab: -<pre> -crontab -e -</pre> -<p> -and add these 3 lines at the end: +Do a real reseed test on *another* I2P router machine: +<ul> +<li>include manually new ssl-certificate into i2p installation: ~/i2p/certificates/ssl/ +<li>include manually new public reseed key into i2p installation: ~/i2p/certificates/reseed/ +<li>http://localhost:7657/configreseed --> remove all reseed hosts +<li>add the new reseed host e.g. "https://your-server.com/" *without* trailing "i2pseeds.su3" +<li>Save and Shutdown router. +<li>clear netdb: empty folder ./i2p/netDb. +<li>Restart I2P and watch the I2P router log: <pre> -@reboot /home/i2p/bin/seedserver startdelayed -04 14 * * 2 /home/i2p/bin/seedserver restart -#end +2014/10/13 23:01:02 | Reseed start +2014/10/13 23:01:02 | Reseeding from https://your-server/i2pseeds.su3 +2014/10/13 23:01:05 | INFO: xx files extracted to /tmp/i2p-V2qudTbd.tmp/reseeds-1010682701 +2014/10/13 23:01:05 | Reseed got xx router infos from https://your-server.com/i2pseeds.su3 with 0 errors +2014/10/13 23:01:06 | Reseed complete, xx received </pre> +</ul> -<p> -Save and close the editor. It would be good to check if this is properly working when you reboot your machine. + + + +<h3>13. Contact reseed maintainer</h3> <p> -"seedserver" shell script: +Contact us per email backup@mail.i2p (fallback is killyourtv@mail.i2p or the reseed section at zzz's forum) +Provide us details about the new +<ul> +<li>reseed website url, +<li>public part of ssl-certificate +<li>public su3-key +<li>your contact email +</ul> +<p> +Feel free to contact backup@mail.i2p in case of questions or problems or post your question at zzz's forum in the reseed section. + + + +<h3>14. Script - cronjob_i2p.sh</h3> <pre> -###################################################################################################### +############################################################################### #!/bin/sh +version="v5" -# Your settings -toolpath=/home/i2p/bin -tlsHost=myserver.com -signer=myemail@mail.i2p -netdb="/home/i2p/.i2p/netDb" +# CONFIG +I2P="${HOME}/i2p" # i2p installation directory +source="${HOME}/.i2p/netDb" # valid netdb +target="${HOME}/i2pseeds.su3" # location for the final su3-files -tool=i2p-tools -logpath="$toolpath/${tool}.log" -logfile="$logpath/reseed.log" -errfile="$logpath/reseed.error" +key_keystore="${I2P}/keystore.ks" # your private su3 reseed key +key_password="secret" # your password for private key of keystore.ks +key_email=yourmail@mail.i2p # your email id for reseeding +key_type=RSA_SHA512_4096 # your key size/type for reseeding (DO NOT EDIT, unless you know why) -cd "$toolpath" -mkdir --parents "$logpath" +tool_zip="/usr/bin/zip" # install a "zip" tool: sudo apt-get install zip +tool_i2p="$I2P/lib/i2p.jar" # should be already there -do_status() { -/bin/sleep 1 -if [ -n "$(pgrep -x "$tool")" ]; then -echo "$tool running, pid $(pgrep "$tool")" -else -echo "$tool not running." -fi; -} +# CONFIG (DO NOT EDIT) +ri_seed=75 # average number ri per su3-file (DO NOT EDIT) +stamp=$(date +%s) # unique id (DO NOT EDIT) +target_tmp="/tmp/i2pseeds.${stamp}.tmp" # temp folder with unique id (DO NOT EDIT) -do_start() { -if [ -z "$(pgrep -x "$tool")" ]; then -do_logrotate -nohup "$toolpath/$tool" reseed -tlsHost="$tlsHost" --signer="$signer" --netdb="$netdb" > "$logfile" 2> "$errfile" & -fi; -do_status -} -do_stop() { -if [ -n "$(pgrep -x "$tool")" ]; then -pkill "$tool" -fi; -do_status -} +# CLEAN /tmp/i2pseeds.* +find /tmp -type d -iname 'i2pseeds.*.tmp' -exec rm -rf {} \; +mkdir --parents "${target_tmp}" -do_startdelayed() { -echo "waiting 20s..." -/bin/sleep 20 -do_start -} -do_restart() { -do_status -do_stop -do_start -} +# CHECK REQUIREMENT +[ ! -d "${I2P}" ] && echo "ERROR1: path not found: ${I2P}" && exit 1 +[ ! -d "${source}" ] && echo "ERROR2: path not found: ${source}" && exit 1 +[ ! -d "${target_tmp}" ] && echo "ERROR3: path not found: ${target_tmp}" && exit 1 +[ ! -x "${tool_zip}" ] && echo "ERROR4: command not found: ${tool_zip}" && exit 1 +[ ! -f "${tool_i2p}" ] && echo "ERROR5: file not found: ${tool_i2p}" && exit 1 +[ ! -f "${key_keystore}" ] && echo "ERROR6: file not found: ${key_keystore}" && exit 1 -do_logrotate() { -do_status -if [ -z "$(pgrep -x "$tool")" ]; then -mv --force "${logfile}.6" "${logfile}.7" 2>/dev/null -mv --force "${logfile}.5" "${logfile}.6" 2>/dev/null -mv --force "${logfile}.4" "${logfile}.5" 2>/dev/null -mv --force "${logfile}.3" "${logfile}.4" 2>/dev/null -mv --force "${logfile}.2" "${logfile}.3" 2>/dev/null -mv --force "${logfile}.1" "${logfile}.2" 2>/dev/null -mv --force "${logfile}" "${logfile}.1" 2>/dev/null -mv --force "${errfile}.6" "${errfile}.7" 2>/dev/null -mv --force "${errfile}.5" "${errfile}.6" 2>/dev/null -mv --force "${errfile}.4" "${errfile}.5" 2>/dev/null -mv --force "${errfile}.3" "${errfile}.4" 2>/dev/null -mv --force "${errfile}.2" "${errfile}.3" 2>/dev/null -mv --force "${errfile}.1" "${errfile}.2" 2>/dev/null -mv --force "${errfile}" "${errfile}.1" 2>/dev/null -echo "log-rotate done." -else -echo "log-rotate not possible." -fi; -} -do_showlog() { -echo "-------------------------------------------------------------------------------" -tail "$errfile" -echo "-------------------------------------------------------------------------------" -tail "$logfile" -echo "-------------------------------------------------------------------------------" -} +# CREATE index-files from netdB: use only 66% and max. 10h old +find "${source}" -type f -mmin -600 -name 'routerInfo-*.dat' | awk -v ri_seed="${ri_seed}" -v target_tmp="${target_tmp}" ' + BEGIN { ri_all=0; } + { data[ri_all++]=$0; } + END { srand(); + ri_use=ri_all*0.6666; + ri_su3=int(ri_use/10); + stepy=ri_use/ri_all; + stepx=ri_seed/ri_use; + for (y=0;y<ri_all; y++) if (rand()<=stepy) { + for (x=0; x<ri_su3; x++) if (rand()<=stepx) { + file=target_tmp"/"x".index"; + print data[y] >> file + } + } + }' -do_usage() { -echo "Usage: {start|stop|status|restart|logrotate|startdelayed|showlog}" -} +# CREATE zip-files from index-files +find "${target_tmp}" -type f -name '*.index' | sort | while read i; do + "${tool_zip}" --update --quiet --junk-paths "${target_tmp}/$(basename "$i" .index)" -@ < "$i" +done + + +# CREATE su3-files from zip-files +echo "${key_password}" | java -cp "${tool_i2p}" net.i2p.crypto.SU3File bulksign -c RESEED -t "${key_type}" "${target_tmp}" "${key_keystore}" "${stamp}" "${key_email}" + + +# REMOVE index-files and zip-files +find "${target_tmp}" -type f -name '*.index' -exec rm -f "{}" \; +find "${target_tmp}" -type f -name '*.zip' -exec rm -f "{}" \; + + +# FINAL CHECK number su3-files +c_su3=$(find "${target_tmp}" -type f -mmin -600 -name '*.su3' | wc -l) +[ "${c_su3}" -lt 25 ] && echo "ERROR7: less than 25 su3 files found: ${c_su3}" && rm -Rf "${target_tmp}" && exit 1 +echo "Created: $target_tmp ${c_su3} x${ri_seed}" -case "$1" in -start) -do_start -;; -stop) -do_stop -;; -status) -do_status -;; -restart) -do_restart -;; -startdelayed) -do_startdelayed -;; -logrotate) -do_logrotate -;; -showlog) -do_showlog -;; -*) -do_usage -;; -esac +# MOVE su3-files to target +chmod 755 "${target_tmp}" -R +rm -fr "${target}.old" +mv -f "${target}" "${target}.old" +mv -f "${target_tmp}" "${target}" +rm -fr "${target_tmp}" + + +# EXIT +echo "$(basename "$0")" "${version} ${target} ${c_su3} x${ri_seed}" +logger -t "$(basename "$0")" "${version} ${target} ${c_su3} x${ri_seed}" exit 0 -###################################################################################################### +############################################################################### </pre> +<h3>15. Script - su3.php</h3> +<pre> +############################################################################### +<?php +$version="v5"; -<h3>23. matt's go solution - reverse-proxy setup</h3> -<p> -You can run i2p-tools also behind your normal web-server (reverse-proxy). +# CONFIG +$path_su3="/home/i2p/i2pseeds.su3"; # path to pre-calculated su3 files +$salt="change_to_something"; # change salt to something random +$salt=$salt . date("Y-m-d"); # date() ensures a rotate once a day, even if su3 are not updated daily (DO NOT EDIT) +$file_su3 = "i2pseeds.su3"; # static (DO NOT EDIT) +$user_agent= "Wget/1.11.4"; # static (DO NOT EDIT) -<p> -The web-server handles the TLS handshake, encryption, SSL Certificate and the logfiles. -But you don't need the scripts su3.php and the shell cronjob for creating su3-files. -i2p-tools is running "behind" the web-server, without TLS management, only bind to -local interface 127.0.0.1 and is handling complete building and handling of su3-files. +# INSIDE i2p-net ? If yes: convert DESTB32 into pseudo IPv6 as valid REMOTE_ADDR +if ( $_SERVER["REMOTE_ADDR"]=="127.0.0.1" + && isset($_SERVER["HTTP_X_I2P_DESTB32"]) + ) { $_SERVER["REMOTE_ADDR"]=inet_ntop(substr(md5($_SERVER["HTTP_X_I2P_DESTB32"]),0,16)); } -<p> -Run i2p-tools with this command: -<pre> -i2p-tools reseed --signer test@test.de --key /path_to/test_at_test.de.pem --netdb /path_to/netDb --port=8443 --ip 127.0.0.1 --trustProxy -</pre> +# HEALTH CHECK 1 +if ( !isset($_SERVER['HTTP_USER_AGENT']) + || !isset($_SERVER['REMOTE_ADDR']) + || !isset($_GET['file']) + ) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } -Important notes for this special setup: -<ul> -<li>do *not* specify --tlsHost, --tlsCert or --tlsKey on the command-line -<li>"ip 127.0.0.1" binds the program only to local interface -<li>"trustProxy" uses the "X-Forwarded-For" to get the real client IP -</ul> -"trustProxy" uses the "X-Forwarded-For" to get the real client IP +# COUNT su3 files +$count_su3 = count(glob($path_su3."/*.su3")); -<p> -lighttpd configuration example: -<pre> - server.modules += ( "mod_proxy" ) - proxy.server = ( ".su3" => ( ( "host" => "127.0.0.1", "port" => 8443 ) ) ) -</pre> +# HEALTH CHECK 2 +if ( empty($_SERVER['HTTP_USER_AGENT']) + || empty($_SERVER['REMOTE_ADDR']) + || empty($_GET['file']) + || (strcmp(basename($_GET['file']), $file_su3) != 0) + || (strcmp($_SERVER['HTTP_USER_AGENT'], $user_agent) != 0) + || !filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) + || $count_su3<1 + ) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } -<p> -nginx configuration example: -<pre> - location / { - proxy_pass http://127.0.0.1:8443; - } -</pre> +# MAPPING Client IP to one su3-file +$remote_id = inet_pton($_SERVER['REMOTE_ADDR']); +$shrink=3; if (strlen($remote_id)>8) { $shrink=8; }; +$remote_id = abs(crc32(md5(substr($remote_id,0,$shrink).$salt))) % $count_su3; +$file_id = $path_su3."/".$remote_id.".su3"; -<p> -and for X-Forwarded-For: -<pre> - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + +# HEALTH CHECK 3 +if (!file_exists($file_id)) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } + + +# PROVIDE su3-file +header('Content-Description: File Transfer'); +header("Content-Type: application/zip"); +header('Content-Transfer-Encoding: binary'); +header('Content-Length: '.filesize($file_id)); +header('Content-Disposition: attachment; filename='.$file_su3); +ob_clean(); flush(); +if (!readfile($file_id)) { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); die(); } +exit; +?> +############################################################################### </pre> +<h3>16. Optional - setup a manual reseed method</h3> +<p> +For some users the automated reseeding may not work. +This is an alternate way for users to get a valid reseed file with a normal web-browser, +e.g. from another machine or maybe a friend. It is secured by a captcha to prevent abuse. -<h3>24. matt's go solution - Convert existing Java keystore to crt- and pem-file</h3> +<p> +With this optional code users can visit https://your.reseedserver.com/reseed.php +with any web-browser to download a su3-file after they solved the captcha. <p> -This describes how to convert your existing Java keystore with your su3 signing key to a plain crt- and pem-file. -This is only needed, when you already have a Java keystore and want to use matt's go solution. -If you create new keys+certs with matt's solution you can skip this chapter! +Since 0.9.18-9 I2P has support to use reseed files from other sources: +http://localhost:7657/configreseed <p> -Requirements: -<ul> -<li>Java keytool -<li>openssl -<li>and of course your secret password for the keystore -</ul> +Visit https://geti2p.net/en/faq#manual_reseed to read how it works for users and see some example url's. +[NOT DONE YET: read here: <a href="http://zzz.i2p/topics/1828-running-prototype-manually-reseed-captcha">zzz.i2p</a> +or test here anonymously: <a href="http://reseed.i2p/open.php">reseed.i2p</a>] <p> -Keep in mind: the Java keystore has two passwords: +The changes for an exiting reseed server with the previous setup are simple: <ul> -<li>the secret key password you have entered while creating your keystore the first time (SU3File keygen ...) -<li>and a "storage" password, which is most probably default "changeit". +<li>use the latest su3.php from above (minimal version 5, only minor changes, no change of logic). +<li>add the new reseed.php to your /var/www folder, next to to su3.php +<li>install php5-gd (restart of PHP processes may be necessary) +<li>get Securimage php-code from https://www.phpcaptcha.org/ </ul> <p> -This works in a Ubuntu/Debian shell: +Quote from https://www.phpcaptcha.org (2015-03): +"Securimage is an open-source free PHP CAPTCHA script for generating complex images and CAPTCHA codes to protect +forms from spam and abuse. It can be easily added into existing forms on your website to provide protection from spam bots. +It can run on most any web server as long as you have PHP installed, and GD support within PHP. +Securimage does everything from generating the CAPTCHA images to validating the typed code." -<pre> -###################################################################################################### -file="keystore.ks" -pass_jks=changeit +<p> +Short overview about installing Securimage: +<ol> +<li>download at https://www.phpcaptcha.org/download/ +<li>extract to /var/www/securimage +<li>download and extract the "Test Script" (securimage_test.php) from the same url +<li>test your server and visit https://.../securimage_test.php with your browser +</ol> +<p> +The "Test Script" verifies your ability to run and display the captcha code, and can be deleted after the test. -# List the keystore content, show the included (email) alias -keytool -list -storepass $pass_jks -keystore $file +<p> +The reseed.php contains only the captcha generation and verification of the users input. It is based on the +Quickstart Guide from Securimage. When the user solved the captcha, reseed.php sets two http variables and +then includes the external su3.php to start the su3-file download. -# Convert jks --> pkcs12, specify the correct email alias (xxxxx@mail.i2p): -keytool -importkeystore -srcalias xxxxx@mail.i2p -srckeystore $file -srcstoretype jks -srcstorepass $pass_jks -destkeystore ${file}.p12 -deststoretype pkcs12 -deststorepass $pass_jks -destkeypass $pass_jks +<p> +The name "reseed.php" is not fixed, you can name it unremarkable/unobtrusive as you like, +enter.php start.php go.php... +but you have to stick with it, when it is published :-) -# Show the pkcs12 content: -openssl pkcs12 -passin pass:$pass_jks -in ${file}.p12 -nodes -info +<p> +reseed.php: +<pre> +################################################################################################ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body> +<?php +session_start(); +include_once $_SERVER['DOCUMENT_ROOT'] . '/securimage/securimage.php'; +$securimage = new Securimage(); + +if (!isset($_POST['captcha_code']) || $securimage->check($_POST['captcha_code']) == false) {?> + <form method="post" action="<?php echo(basename($_SERVER['PHP_SELF'])); ?>"> + <img id="captcha" src="/securimage/securimage_show.php" alt="CAPTCHA Image" /> + <p>Enter Code: <input type="text" name="captcha_code" size="10" maxlength="6" /> + <input type="submit" value="Check Code" /> + </form> +<?php } else { + $_SERVER['HTTP_USER_AGENT']="Wget/1.11.4"; + $_GET['file']="i2pseeds.su3"; + include_once $_SERVER['DOCUMENT_ROOT'] . "/su3.php"; +} ?> +</body></html> +################################################################################################ +</pre> -# Convert pkcs12 --> pem -openssl pkcs12 -passin pass:$pass_jks -in ${file}.p12 -nodes -out ${file}.pem -# Decrypt the pem -openssl rsa -in ${file}.pem -out xxxxx_at_mail.i2p.pem -# Extract the certificate -openssl x509 -in ${file}.pem -out xxxxx_at_mail.i2p.crt -###################################################################################################### -</pre> {% endblock %} -- GitLab