Compare commits
221 Commits
v0.0.1
...
yggdrasil-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
62dad14e00 | ||
![]() |
d996dca292 | ||
![]() |
56e0395e68 | ||
![]() |
bf1503bcc7 | ||
![]() |
2aef3b6bf1 | ||
![]() |
8fbef0fca9 | ||
![]() |
24c6ff88dd | ||
![]() |
8da5f98b0c | ||
![]() |
416399e78f | ||
![]() |
80cde5f300 | ||
![]() |
3413faf5c9 | ||
![]() |
eb5d4f5cce | ||
![]() |
60d2f906d2 | ||
![]() |
fac4d0147f | ||
![]() |
c2d32d78f0 | ||
![]() |
e95797eca1 | ||
![]() |
2db015addb | ||
![]() |
d8289a4834 | ||
![]() |
59431496db | ||
![]() |
7fefd783b2 | ||
![]() |
69ef8a0344 | ||
![]() |
f74f7f8c98 | ||
![]() |
421bba5f03 | ||
![]() |
7689fb1321 | ||
![]() |
04c94cd2ba | ||
![]() |
64b79e0f82 | ||
![]() |
5e5c9c0d2f | ||
![]() |
3088a5b6d0 | ||
![]() |
3859e539c5 | ||
![]() |
6249b3f41e | ||
![]() |
8ed93440a4 | ||
![]() |
bd4f7d746d | ||
![]() |
d7bf080c43 | ||
![]() |
acaf528e9b | ||
![]() |
98293c4ded | ||
![]() |
c9c938911d | ||
![]() |
7b27889b3b | ||
![]() |
a8b0285358 | ||
![]() |
a734aef44b | ||
![]() |
3cdda753f2 | ||
![]() |
1bddf97144 | ||
![]() |
e07fffd966 | ||
![]() |
ca652b3ecd | ||
![]() |
2c0f017eb0 | ||
![]() |
78caae5ac0 | ||
![]() |
82252bc50d | ||
![]() |
7ac0b1d9a1 | ||
![]() |
573a2d900c | ||
![]() |
9e4aa1ca50 | ||
![]() |
3491bbc9dc | ||
![]() |
045b11ce3b | ||
![]() |
492e0e2bbf | ||
![]() |
21cea69829 | ||
![]() |
1cb8a524ba | ||
![]() |
7ca050375f | ||
![]() |
45605da257 | ||
![]() |
3f37746aed | ||
![]() |
aa1948d04f | ||
![]() |
a41291ec20 | ||
![]() |
2cfa5fda1e | ||
![]() |
e6ed4250e2 | ||
![]() |
49e6d184c1 | ||
![]() |
63cd3e5189 | ||
![]() |
645d80cc7c | ||
![]() |
b3cdb618a6 | ||
![]() |
3f5922db47 | ||
![]() |
8eb780f6a0 | ||
![]() |
9611dfee04 | ||
![]() |
11b64d04eb | ||
![]() |
eaa091971e | ||
![]() |
1203fbbc53 | ||
![]() |
104b5d7486 | ||
![]() |
716c56967c | ||
![]() |
d1d2721e36 | ||
![]() |
a46870bb72 | ||
![]() |
797165ad8b | ||
![]() |
3366f0ffdc | ||
![]() |
2d3f1a540d | ||
![]() |
710a1faac2 | ||
![]() |
99ae995fa0 | ||
![]() |
76b5e6b2e8 | ||
![]() |
1acf807a13 | ||
![]() |
9a7353a6e8 | ||
![]() |
166f62cbe3 | ||
![]() |
7188a28ebd | ||
![]() |
231c9f07bd | ||
![]() |
5abecda122 | ||
![]() |
48ee44606a | ||
![]() |
5107f25aa5 | ||
![]() |
6b847ca8b3 | ||
![]() |
bb7dff6890 | ||
![]() |
d86a60af37 | ||
![]() |
6a1365956b | ||
![]() |
06ebccb4ee | ||
![]() |
07b4e1fb53 | ||
![]() |
683dbc85fc | ||
![]() |
5ecc79b054 | ||
![]() |
c607bb9fd3 | ||
![]() |
8e89742f4a | ||
![]() |
3776c09db5 | ||
![]() |
0f5a04da1b | ||
![]() |
0dd22d990a | ||
![]() |
8c8ba765cd | ||
![]() |
c7ac947d70 | ||
![]() |
d6c67830f9 | ||
![]() |
d6354e2bc2 | ||
![]() |
8b7ba5a4a5 | ||
![]() |
ac8a6dbe91 | ||
![]() |
f33d1592c8 | ||
![]() |
641eb5dfa4 | ||
![]() |
694b2a67c0 | ||
![]() |
ca2fd4873a | ||
![]() |
4f39a50ce6 | ||
![]() |
2f067908ba | ||
![]() |
2a286e1383 | ||
![]() |
65a150c5b2 | ||
![]() |
d9efd86c21 | ||
![]() |
054a28c22a | ||
![]() |
8775895d20 | ||
![]() |
a8d6b05fb9 | ||
![]() |
d79ea5d92f | ||
![]() |
77c7e6c08c | ||
![]() |
36783b4587 | ||
![]() |
71e6743206 | ||
![]() |
33cdebd325 | ||
![]() |
86a183c9fa | ||
![]() |
accce088e6 | ||
![]() |
42beefd223 | ||
![]() |
12b71780a1 | ||
![]() |
b444857549 | ||
![]() |
2004e84df8 | ||
![]() |
7441572846 | ||
![]() |
93dd1b4e8d | ||
![]() |
398a6182af | ||
![]() |
d467b652ec | ||
![]() |
19c29cfdc6 | ||
![]() |
1548d1e36b | ||
![]() |
3e8ace902d | ||
![]() |
8afd6c6f28 | ||
![]() |
b94bd86d03 | ||
![]() |
7829962acd | ||
![]() |
299421e0fe | ||
a7c097d232 | |||
7282cb5fa0 | |||
2f8508ee92 | |||
b036b9e8f8 | |||
f36a500210 | |||
dbcf640320 | |||
08f2f9031d | |||
d40d687f6e | |||
b12bf1bf22 | |||
7bcc9344ec | |||
f84eb3ce70 | |||
f576588ec0 | |||
0ae229792c | |||
4e69e3d50b | |||
059a24d638 | |||
45071f0faa | |||
0791f1145b | |||
51c58d6407 | |||
0bf519a351 | |||
1eb8e6fb5c | |||
c4b8236446 | |||
162c6fb01a | |||
11c6b51be6 | |||
17712bf3ae | |||
7a438a29ed | |||
b0cd962ce9 | |||
92462d8986 | |||
8d1a4408ce | |||
179688d8c0 | |||
cb674587f6 | |||
dc0ec87635 | |||
4c86b4fd8a | |||
d48d8e217d | |||
0ac1d8ad65 | |||
c46fcb14f7 | |||
3ec7aace8a | |||
07b65bee1f | |||
1589518259 | |||
9fe7931202 | |||
8daf43276b | |||
2173a6a36e | |||
f9c992dcb2 | |||
fd9eae23eb | |||
![]() |
53eeba13a8 | ||
![]() |
e093175340 | ||
![]() |
81ea32f49c | ||
![]() |
731eaa0d11 | ||
![]() |
785a8f6b68 | ||
![]() |
7e2176986e | ||
![]() |
e630a6fe72 | ||
![]() |
352fdf2566 | ||
![]() |
d73ca116f8 | ||
![]() |
e506f38630 | ||
![]() |
4284b9ee04 | ||
![]() |
11d1479dcf | ||
![]() |
82b8f97ba4 | ||
![]() |
9ed8caaec3 | ||
![]() |
54edb1b12e | ||
![]() |
824441fa69 | ||
![]() |
da1beba872 | ||
![]() |
7c304110cd | ||
![]() |
0937e09acf | ||
![]() |
7a0bb222b9 | ||
![]() |
86a2b5f208 | ||
![]() |
2ef4aa08f9 | ||
![]() |
8b72c37a3b | ||
![]() |
2e55be1a20 | ||
![]() |
1b5e875113 | ||
![]() |
bca841c799 | ||
![]() |
c83775c361 | ||
![]() |
3aa32bcd7f | ||
![]() |
395aa73b17 | ||
![]() |
01153a9ee8 | ||
![]() |
eb0703485f | ||
![]() |
dac3888397 | ||
![]() |
83918dfff8 | ||
![]() |
54271fb852 | ||
![]() |
d5e81baf12 | ||
![]() |
8dfdb5b9d2 |
23
.dockerignore
Normal file
23
.dockerignore
Normal file
@@ -0,0 +1,23 @@
|
||||
.idea
|
||||
.git
|
||||
.gitlab-ci.yml
|
||||
.vscode
|
||||
|
||||
# CI cache folder storing docker images
|
||||
ci-exports
|
||||
|
||||
/i2p-tools
|
||||
/cert.pem
|
||||
/key.pem
|
||||
/_netdb
|
||||
i2pseeds.su3
|
||||
*.pem
|
||||
onion.key
|
||||
tmp/
|
||||
i2p-tools-*
|
||||
*.crl
|
||||
*.crt
|
||||
*.pem
|
||||
plugin
|
||||
reseed-tools*
|
||||
data-dir*
|
8
.gitignore
vendored
8
.gitignore
vendored
@@ -5,3 +5,11 @@
|
||||
i2pseeds.su3
|
||||
*.pem
|
||||
onion.key
|
||||
tmp/
|
||||
i2p-tools-*
|
||||
*.crl
|
||||
*.crt
|
||||
*.pem
|
||||
plugin
|
||||
reseed-tools*
|
||||
data-dir*
|
106
.gitlab-ci.yml
Normal file
106
.gitlab-ci.yml
Normal file
@@ -0,0 +1,106 @@
|
||||
image: docker:19.03.12
|
||||
|
||||
stages:
|
||||
- docker_test
|
||||
- docker_push
|
||||
|
||||
variables:
|
||||
# When using dind service, we need to instruct docker to talk with
|
||||
# the daemon started inside of the service. The daemon is available
|
||||
# with a network connection instead of the default
|
||||
# /var/run/docker.sock socket. Docker 19.03 does this automatically
|
||||
# by setting the DOCKER_HOST in
|
||||
# https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29
|
||||
#
|
||||
# The 'docker' hostname is the alias of the service container as described at
|
||||
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
|
||||
#
|
||||
# Specify to Docker where to create the certificates, Docker will
|
||||
# create them automatically on boot, and will create
|
||||
# `/certs/client` that will be shared between the service and job
|
||||
# container, thanks to volume mount from config.toml
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
|
||||
DOCKER_HOST: tcp://docker:2376
|
||||
|
||||
services:
|
||||
- docker:19.03.12-dind
|
||||
|
||||
.docker_cache:
|
||||
cache:
|
||||
# The same key should be used across branches
|
||||
key: "$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- ci-exports/*.tar
|
||||
|
||||
# Make sure we can build a docker image
|
||||
# It's cached for later jobs
|
||||
build_docker:
|
||||
extends:
|
||||
- .docker_cache
|
||||
stage: docker_test
|
||||
script:
|
||||
# Try to load latest branch image from local tar or from registry
|
||||
- docker load ci-exports/$CI_COMMIT_REF_SLUG.tar || docker pull $CI_REGISTRY_IMAGE:latest || true
|
||||
- docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
|
||||
- mkdir -p ci-exports/
|
||||
- docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
|
||||
|
||||
# Publishes the configured CI registry (by default that's gitlab's registry)
|
||||
push_ci_registry:
|
||||
extends:
|
||||
- .docker_cache
|
||||
stage: docker_push
|
||||
cache:
|
||||
policy: pull
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- cat ci-exports/$CI_COMMIT_REF_SLUG.tar | docker load
|
||||
- docker tag $CI_REGISTRY_IMAGE:latest $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
|
||||
- docker push $CI_REGISTRY_IMAGE:latest
|
||||
only:
|
||||
refs:
|
||||
# Make sure to protect these tags!
|
||||
- /^v(\d+\.){2,3}\d+$/
|
||||
- /.+-release$/
|
||||
variables:
|
||||
- $CI_REGISTRY
|
||||
- $CI_REGISTRY_USER
|
||||
- $CI_REGISTRY_PASSWORD
|
||||
- $CI_REGISTRY_IMAGE
|
||||
|
||||
# Publishes the cached image to docker
|
||||
push_dockerhub_registry:
|
||||
extends:
|
||||
- .docker_cache
|
||||
stage: docker_push
|
||||
cache:
|
||||
policy: pull
|
||||
before_script:
|
||||
- docker login -u $DOCKERHUB_REGISTRY_USER -p $DOCKERHUB_REGISTRY_PASSWORD $DOCKERHUB_REGISTRY
|
||||
script:
|
||||
- cat ci-exports/$CI_COMMIT_REF_SLUG.tar | docker load
|
||||
- docker tag $CI_REGISTRY_IMAGE:latest $DOCKERHUB_REGISTRY_IMAGE:$CI_COMMIT_TAG
|
||||
- docker tag $CI_REGISTRY_IMAGE:latest $DOCKERHUB_REGISTRY_IMAGE:latest
|
||||
- docker push $DOCKERHUB_REGISTRY_IMAGE:$CI_COMMIT_TAG
|
||||
- docker push $DOCKERHUB_REGISTRY_IMAGE:latest
|
||||
# Push the readme to dockerhub
|
||||
- >-
|
||||
docker run -v $PWD:/workspace
|
||||
-e DOCKERHUB_USERNAME="$DOCKERHUB_REGISTRY_USER"
|
||||
-e DOCKERHUB_PASSWORD="$DOCKERHUB_REGISTRY_PASSWORD"
|
||||
-e DOCKERHUB_REPOSITORY="$DOCKERHUB_REGISTRY_IMAGE"
|
||||
-e README_FILEPATH='/workspace/README.md'
|
||||
peterevans/dockerhub-description:2
|
||||
only:
|
||||
refs:
|
||||
# Make sure to protect these tags!
|
||||
- /^v(\d+\.){2,3}\d+$/
|
||||
- /.+-release$/
|
||||
variables:
|
||||
- $DOCKERHUB_REGISTRY
|
||||
- $DOCKERHUB_REGISTRY_USER
|
||||
- $DOCKERHUB_REGISTRY_PASSWORD
|
||||
- $DOCKERHUB_REGISTRY_IMAGE
|
146
CHANGELOG.html
Normal file
146
CHANGELOG.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
I2P Reseed Tools
|
||||
</title>
|
||||
<meta name="author" content="eyedeekay" />
|
||||
<meta name="description" content="reseed-tools" />
|
||||
<meta name="keywords" content="yggdrasil-direct" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<a href="#shownav">
|
||||
Show navigation
|
||||
</a>
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="CHANGELOG.html">
|
||||
CHANGELOG
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="DOCKER.html">
|
||||
DOCKER
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EXAMPLES.html">
|
||||
EXAMPLES
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
<a href="#hidenav">
|
||||
Hide Navigation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
2021-12-16
|
||||
* app.Version = “0.2.11”
|
||||
* include license file in plugin
|
||||
</p>
|
||||
<p>
|
||||
2021-12-14
|
||||
* app.Version = “0.2.10”
|
||||
* restart changelog
|
||||
* fix websiteURL in plugin.config
|
||||
</p>
|
||||
<p>
|
||||
2019-04-21
|
||||
* app.Version = “0.1.7”
|
||||
* enabling TLS 1.3
|
||||
<em>
|
||||
only
|
||||
</em>
|
||||
</p>
|
||||
<p>
|
||||
2016-12-21
|
||||
* deactivating previous random time delta, makes only sense when patching ri too
|
||||
* app.Version = “0.1.6”
|
||||
</p>
|
||||
<p>
|
||||
2016-10-09
|
||||
* seed the math random generator with time.Now().UnixNano()
|
||||
* added 6h+6h random time delta at su3-age to increase anonymity
|
||||
* app.Version = “0.1.5”
|
||||
</p>
|
||||
<p>
|
||||
2016-05-15
|
||||
* README.md updated
|
||||
* allowed routerInfos age increased from 96 to 192 hours
|
||||
* app.Version = “0.1.4”
|
||||
</p>
|
||||
<p>
|
||||
2016-03-05
|
||||
* app.Version = “0.1.3”
|
||||
* CRL creation added
|
||||
</p>
|
||||
<p>
|
||||
2016-01-31
|
||||
* allowed TLS ciphers updated (hardened)
|
||||
* TLS certificate generation: RSA 4096 –> ECDSAWithSHA512 384bit secp384r1
|
||||
* ECDHE handshake: only CurveP384 + CurveP521, default CurveP256 removed
|
||||
* TLS certificate valid: 2y –> 5y
|
||||
* throttled.PerDay(4) –> PerHour(4), to enable limited testing
|
||||
* su3 RebuildInterval: 24h –> 90h, higher anonymity for the running i2p-router
|
||||
* numRi per su3 file: 75 –> 77
|
||||
</p>
|
||||
<p>
|
||||
2016-01
|
||||
* fork from
|
||||
<a href="https://i2pgit.org/idk/reseed-tools" rel="nofollow">
|
||||
https://i2pgit.org/idk/reseed-tools
|
||||
</a>
|
||||
</p>
|
||||
<div>
|
||||
<a href="#show">
|
||||
Show license
|
||||
</a>
|
||||
<div id="show">
|
||||
<div id="hide">
|
||||
<pre><code>Copyright (c) 2014 Matt Drollette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</code></pre>
|
||||
<a href="#hide">
|
||||
Hide license
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<iframe src="https://snowflake.torproject.org/embed.html" width="320" height="240" frameborder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://geti2p.net/">
|
||||
I2P
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,3 +1,12 @@
|
||||
2021-12-16
|
||||
* app.Version = "0.2.11"
|
||||
* include license file in plugin
|
||||
|
||||
2021-12-14
|
||||
* app.Version = "0.2.10"
|
||||
* restart changelog
|
||||
* fix websiteURL in plugin.config
|
||||
|
||||
2019-04-21
|
||||
* app.Version = "0.1.7"
|
||||
* enabling TLS 1.3 *only*
|
||||
@@ -31,4 +40,4 @@
|
||||
* numRi per su3 file: 75 --> 77
|
||||
|
||||
2016-01
|
||||
* fork from https://github.com/MDrollette/i2p-tools
|
||||
* fork from https://i2pgit.org/idk/reseed-tools
|
||||
|
168
DOCKER.html
Normal file
168
DOCKER.html
Normal file
@@ -0,0 +1,168 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
I2P Reseed Tools
|
||||
</title>
|
||||
<meta name="author" content="eyedeekay" />
|
||||
<meta name="description" content="reseed-tools" />
|
||||
<meta name="keywords" content="yggdrasil-direct" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<a href="#shownav">
|
||||
Show navigation
|
||||
</a>
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="CHANGELOG.html">
|
||||
CHANGELOG
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="DOCKER.html">
|
||||
DOCKER
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EXAMPLES.html">
|
||||
EXAMPLES
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
<a href="#hidenav">
|
||||
Hide Navigation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3>
|
||||
Docker
|
||||
</h3>
|
||||
<p>
|
||||
To make it easier to deploy reseeds, it is possible to run this software as a
|
||||
Docker image. Because the software requires access to a network database to host
|
||||
a reseed, you will need to mount the netDb as a volume inside your docker
|
||||
container to provide access to it, and you will need to run it as the same user
|
||||
and group inside the container as I2P.
|
||||
</p>
|
||||
<p>
|
||||
When you run a reseed under Docker in this fashion, it will automatically
|
||||
generate a self-signed certificate for your reseed server in a Docker volume
|
||||
mamed reseed-keys.
|
||||
<em>
|
||||
Back up this directory
|
||||
</em>
|
||||
, if it is lost it is impossible
|
||||
to reproduce.
|
||||
</p>
|
||||
<p>
|
||||
Please note that Docker is not currently compatible with .onion reseeds unless
|
||||
you pass the –network=host tag.
|
||||
</p>
|
||||
<h4>
|
||||
If I2P is running as your user, do this:
|
||||
</h4>
|
||||
<pre><code> docker run -itd \
|
||||
--name reseed \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume $HOME/.i2p/netDb:$HOME/.i2p/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
||||
</code></pre>
|
||||
<h4>
|
||||
If I2P is running as another user, do this:
|
||||
</h4>
|
||||
<pre><code> docker run -itd \
|
||||
--name reseed \
|
||||
--user $(I2P_UID) \
|
||||
--group-add $(I2P_GID) \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume /PATH/TO/USER/I2P/HERE/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
||||
</code></pre>
|
||||
<h4>
|
||||
<strong>
|
||||
Debian/Ubuntu and Docker
|
||||
</strong>
|
||||
</h4>
|
||||
<p>
|
||||
In many cases I2P will be running as the Debian system user
|
||||
<code>
|
||||
i2psvc
|
||||
</code>
|
||||
. This
|
||||
is the case for all installs where Debian’s Advanced Packaging Tool(apt) was
|
||||
used to peform the task. If you used
|
||||
<code>
|
||||
apt-get install
|
||||
</code>
|
||||
this command will
|
||||
work for you. In that case, just copy-and-paste:
|
||||
</p>
|
||||
<pre><code> docker run -itd \
|
||||
--name reseed \
|
||||
--user $(id -u i2psvc) \
|
||||
--group-add $(id -g i2psvc) \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
||||
</code></pre>
|
||||
<div>
|
||||
<a href="#show">
|
||||
Show license
|
||||
</a>
|
||||
<div id="show">
|
||||
<div id="hide">
|
||||
<pre><code>Copyright (c) 2014 Matt Drollette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</code></pre>
|
||||
<a href="#hide">
|
||||
Hide license
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<iframe src="https://snowflake.torproject.org/embed.html" width="320" height="240" frameborder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://geti2p.net/">
|
||||
I2P
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
57
DOCKER.md
Normal file
57
DOCKER.md
Normal file
@@ -0,0 +1,57 @@
|
||||
### Docker
|
||||
|
||||
To make it easier to deploy reseeds, it is possible to run this software as a
|
||||
Docker image. Because the software requires access to a network database to host
|
||||
a reseed, you will need to mount the netDb as a volume inside your docker
|
||||
container to provide access to it, and you will need to run it as the same user
|
||||
and group inside the container as I2P.
|
||||
|
||||
When you run a reseed under Docker in this fashion, it will automatically
|
||||
generate a self-signed certificate for your reseed server in a Docker volume
|
||||
mamed reseed-keys. *Back up this directory*, if it is lost it is impossible
|
||||
to reproduce.
|
||||
|
||||
Please note that Docker is not currently compatible with .onion reseeds unless
|
||||
you pass the --network=host tag.
|
||||
|
||||
#### If I2P is running as your user, do this:
|
||||
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume $HOME/.i2p/netDb:$HOME/.i2p/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
||||
|
||||
#### If I2P is running as another user, do this:
|
||||
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--user $(I2P_UID) \
|
||||
--group-add $(I2P_GID) \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume /PATH/TO/USER/I2P/HERE/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
||||
|
||||
#### **Debian/Ubuntu and Docker**
|
||||
|
||||
In many cases I2P will be running as the Debian system user ```i2psvc```. This
|
||||
is the case for all installs where Debian's Advanced Packaging Tool(apt) was
|
||||
used to peform the task. If you used ```apt-get install``` this command will
|
||||
work for you. In that case, just copy-and-paste:
|
||||
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--user $(id -u i2psvc) \
|
||||
--group-add $(id -g i2psvc) \
|
||||
--publish 443:8443 \
|
||||
--restart always \
|
||||
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer $YOUR_EMAIL_HERE
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM debian:stable-backports
|
||||
ARG I2P_GID=1000
|
||||
ARG I2P_UID=1000
|
||||
COPY . /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools
|
||||
WORKDIR /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools
|
||||
RUN apt-get update && \
|
||||
apt-get dist-upgrade -y && \
|
||||
apt-get install -y git golang-go make && \
|
||||
mkdir -p /var/lib/i2p/i2p-config/reseed && \
|
||||
chown -R $I2P_UID:$I2P_GID /var/lib/i2p && chmod -R o+rwx /var/lib/i2p
|
||||
RUN go build -v -tags netgo -ldflags '-w -extldflags "-static"'
|
||||
USER $I2P_UID
|
||||
WORKDIR /var/lib/i2p/i2p-config/reseed
|
||||
ENTRYPOINT [ "/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/entrypoint.sh" ]
|
132
EXAMPLES.html
Normal file
132
EXAMPLES.html
Normal file
@@ -0,0 +1,132 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
I2P Reseed Tools
|
||||
</title>
|
||||
<meta name="author" content="eyedeekay" />
|
||||
<meta name="description" content="reseed-tools" />
|
||||
<meta name="keywords" content="yggdrasil-direct" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<a href="#shownav">
|
||||
Show navigation
|
||||
</a>
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="CHANGELOG.html">
|
||||
CHANGELOG
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="DOCKER.html">
|
||||
DOCKER
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EXAMPLES.html">
|
||||
EXAMPLES
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
<a href="#hidenav">
|
||||
Hide Navigation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>
|
||||
Example Commands:
|
||||
</h2>
|
||||
<h3>
|
||||
Without a webserver, standalone, automatic OnionV3 with TLS support
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
|
||||
</code></pre>
|
||||
<h3>
|
||||
Without a webserver, standalone, serve P2P with LibP2P
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
|
||||
</code></pre>
|
||||
<h3>
|
||||
Without a webserver, standalone, upload a single signed .su3 to github
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
This one isn’t working yet, I’ll get to it eventually, I’ve got a cooler idea now.
|
||||
<code>
|
||||
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=reseed-tools --ghuser=eyedeekay
|
||||
</code>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Without a webserver, standalone, in-network reseed
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
|
||||
</code></pre>
|
||||
<h3>
|
||||
Without a webserver, standalone, Regular TLS, OnionV3 with TLS
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
|
||||
</code></pre>
|
||||
<h3>
|
||||
Without a webserver, standalone, Regular TLS, OnionV3 with TLS, and LibP2P
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p
|
||||
</code></pre>
|
||||
<h3>
|
||||
Without a webserver, standalone, Regular TLS, OnionV3 with TLS, I2P In-Network reseed, and LibP2P, self-supervising
|
||||
</h3>
|
||||
<pre><code>./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --littleboss=start
|
||||
</code></pre>
|
||||
<div>
|
||||
<a href="#show">
|
||||
Show license
|
||||
</a>
|
||||
<div id="show">
|
||||
<div id="hide">
|
||||
<pre><code>Copyright (c) 2014 Matt Drollette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</code></pre>
|
||||
<a href="#hide">
|
||||
Hide license
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<iframe src="https://snowflake.torproject.org/embed.html" width="320" height="240" frameborder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://geti2p.net/">
|
||||
I2P
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
46
EXAMPLES.md
Normal file
46
EXAMPLES.md
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
## Example Commands:
|
||||
|
||||
### Without a webserver, standalone, automatic OnionV3 with TLS support
|
||||
|
||||
```
|
||||
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, serve P2P with LibP2P
|
||||
|
||||
```
|
||||
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, upload a single signed .su3 to github
|
||||
|
||||
* This one isn't working yet, I'll get to it eventually, I've got a cooler idea now.
|
||||
|
||||
```
|
||||
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=reseed-tools --ghuser=eyedeekay
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, in-network reseed
|
||||
|
||||
```
|
||||
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS
|
||||
|
||||
```
|
||||
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, and LibP2P
|
||||
|
||||
```
|
||||
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, I2P In-Network reseed, and LibP2P, self-supervising
|
||||
|
||||
```
|
||||
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --littleboss=start
|
||||
```
|
315
Makefile
Normal file
315
Makefile
Normal file
@@ -0,0 +1,315 @@
|
||||
|
||||
VERSION=0.2.30
|
||||
APP=reseed-tools
|
||||
USER_GH=eyedeekay
|
||||
CGO_ENABLED=0
|
||||
export CGO_ENABLED=0
|
||||
PLUGIN_PORT=7671
|
||||
export PLUGIN_PORT=7671
|
||||
|
||||
GOOS?=$(shell uname -s | tr A-Z a-z)
|
||||
GOARCH?="amd64"
|
||||
|
||||
ARG=-v -tags netgo -ldflags '-w -extldflags "-static"'
|
||||
|
||||
#MIN_GO_VERSION=`ls /usr/lib/go-1.14 2>/dev/null >/dev/null && echo 1.14`
|
||||
MIN_GO_VERSION?=1.15
|
||||
|
||||
I2P_UID=$(shell id -u i2psvc)
|
||||
I2P_GID=$(shell id -g i2psvc)
|
||||
|
||||
WHOAMI=$(shell whoami)
|
||||
|
||||
echo:
|
||||
@echo "type make version to do release $(APP) $(VERSION) $(GOOS) $(GOARCH) $(MIN_GO_VERSION) $(I2P_UID) $(I2P_GID)"
|
||||
|
||||
index:
|
||||
@echo "<!DOCTYPE html>" > index.html
|
||||
@echo "<html>" >> index.html
|
||||
@echo "<head>" >> index.html
|
||||
@echo " <title>Reseed Tools</title>" >> index.html
|
||||
@echo " <link rel=\"stylesheet\" type=\"text/css\" href =\"/style.css\" />" >> index.html
|
||||
@echo "</head>" >> index.html
|
||||
@echo "<body>" >> index.html
|
||||
pandoc README.md >> index.html
|
||||
@echo "</body>" >> index.html
|
||||
@echo "</html>" >> index.html
|
||||
|
||||
build:
|
||||
go build $(ARG) -o reseed-tools-$(GOOS)-$(GOARCH)
|
||||
|
||||
1.15-build: gofmt
|
||||
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build $(ARG) -o reseed-tools-$(GOOS)-$(GOARCH)
|
||||
|
||||
clean:
|
||||
rm reseed-tools-* tmp -rfv *.deb plugin reseed-tools
|
||||
|
||||
tar:
|
||||
tar --exclude="./.git" --exclude="./tmp" --exclude=".vscode" --exclude="./*.pem" --exclude="./*.crl" --exclude="./*.crt" -cvf ../reseed-tools.tar.xz .
|
||||
|
||||
install:
|
||||
install -m755 reseed-tools-$(GOOS)-$(GOARCH) /usr/bin/reseed-tools
|
||||
install -m644 etc/default/reseed /etc/default/reseed
|
||||
install -m755 etc/init.d/reseed /etc/init.d/reseed
|
||||
mkdir -p /etc/systemd/system/reseed.d/
|
||||
mkdir -p /var/lib/i2p
|
||||
install -g i2psvc -o i2psvc -d /var/lib/i2p/i2p-config/reseed/
|
||||
cp -r content /var/lib/i2p/i2p-config/reseed/content
|
||||
chown -R i2psvc:i2psvc /var/lib/i2p/i2p-config/reseed/
|
||||
install -m644 etc/systemd/system/reseed.d/reseed.conf /etc/systemd/system/reseed.d/reseed.conf
|
||||
install -m644 etc/systemd/system/reseed.d/reseed.service /etc/systemd/system/reseed.d/reseed.service
|
||||
|
||||
uninstall:
|
||||
rm /usr/bin/reseed-tools
|
||||
rm /etc/default/reseed
|
||||
rm /etc/init.d/reseed
|
||||
rm /etc/systemd/system/reseed.d/reseed.conf
|
||||
rm /etc/systemd/system/reseed.d/reseed.service
|
||||
rm -rf /var/lib/i2p/i2p-config/reseed/
|
||||
|
||||
checkinstall: build
|
||||
fakeroot checkinstall \
|
||||
--default \
|
||||
--install=no \
|
||||
--fstrans=yes \
|
||||
--pkgname=reseed-tools \
|
||||
--pkgversion=$(VERSION) \
|
||||
--pkggroup=net \
|
||||
--pkgrelease=1 \
|
||||
--pkgsource="https://i2pgit.org/idk/reseed-tools" \
|
||||
--maintainer="$(SIGNER)" \
|
||||
--requires="i2p,i2p-router" \
|
||||
--suggests="i2p,i2p-router,syndie,tor,tsocks" \
|
||||
--nodoc \
|
||||
--deldoc=yes \
|
||||
--deldesc=yes \
|
||||
--backup=no
|
||||
|
||||
### You shouldn't need to use these now that the go mod require rule is fixed,
|
||||
## but I'm leaving them in here because it made it easier to test that both
|
||||
## versions behaved the same way. -idk
|
||||
|
||||
build-fork:
|
||||
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o reseed-tools-idk
|
||||
|
||||
build-unfork:
|
||||
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o reseed-tools-md
|
||||
|
||||
fork:
|
||||
sed -i 's|idk/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go
|
||||
make gofmt build-fork
|
||||
|
||||
unfork:
|
||||
sed -i 's|idk/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go
|
||||
sed -i 's|RTradeLtd/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go
|
||||
make gofmt build-unfork
|
||||
|
||||
gofmt:
|
||||
gofmt -w main.go cmd/*.go reseed/*.go su3/*.go
|
||||
|
||||
try:
|
||||
mkdir -p tmp && \
|
||||
cd tmp && \
|
||||
../reseed-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p
|
||||
|
||||
stop:
|
||||
mkdir -p tmp && \
|
||||
cd tmp && \
|
||||
../reseed-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p
|
||||
|
||||
docker:
|
||||
docker build -t eyedeekay/reseed .
|
||||
|
||||
docker-push: docker
|
||||
docker push --disable-content-trust=false eyedeekay/reseed:$(VERSION)
|
||||
|
||||
users:
|
||||
docker run --rm eyedeekay/reseed cat /etc/passwd
|
||||
|
||||
docker-ls:
|
||||
docker run --rm \
|
||||
--user $(I2P_UID) \
|
||||
--group-add $(I2P_GID) \
|
||||
--name reseed \
|
||||
--publish 8443:8443 \
|
||||
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb \
|
||||
eyedeekay/reseed ls /var/lib/i2p/i2p-config -lah
|
||||
|
||||
docker-server:
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--user $(I2P_UID) \
|
||||
--group-add $(I2P_GID) \
|
||||
--publish 8443:8443 \
|
||||
--restart=always \
|
||||
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer=hankhill19580@gmail.com
|
||||
docker logs -f reseed
|
||||
|
||||
docker-run:
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--user $(I2P_UID) \
|
||||
--group-add $(I2P_GID) \
|
||||
--publish 8443:8443 \
|
||||
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \
|
||||
eyedeekay/reseed \
|
||||
--signer=hankhill19580@gmail.com
|
||||
|
||||
docker-homerun:
|
||||
docker run -itd \
|
||||
--name reseed \
|
||||
--user 1000 \
|
||||
--group-add 1000 \
|
||||
--publish 8443:8443 \
|
||||
--volume $(HOME)/i2p/netDb:/var/lib/i2p/i2p-config/netDb:z \
|
||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed:z \
|
||||
eyedeekay/reseed \
|
||||
--signer=hankhill19580@gmail.com
|
||||
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/
|
||||
export CGO_CFLAGS=-I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/
|
||||
|
||||
gojava:
|
||||
go get -u -v github.com/sridharv/gojava
|
||||
cp -v ~/go/bin/gojava ./gojava
|
||||
|
||||
jar: gojava
|
||||
echo $(JAVA_HOME)
|
||||
./gojava -v -o reseed.jar -s . build ./reseed
|
||||
|
||||
release: version upload checkinstall upload-single-deb plugins upload-su3s upload-bin
|
||||
|
||||
version:
|
||||
cat README.md | gothub release -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -; true
|
||||
|
||||
delete-version:
|
||||
gothub delete -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION)
|
||||
|
||||
edit:
|
||||
cat README.md | gothub edit -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -
|
||||
|
||||
upload: tar
|
||||
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f ../reseed-tools.tar.xz -n "reseed-tools.tar.xz"
|
||||
|
||||
binary:
|
||||
GOOS=darwin GOARCH=amd64 make build
|
||||
GOOS=darwin GOARCH=arm64 make build
|
||||
GOOS=linux GOARCH=386 make build
|
||||
GOOS=linux GOARCH=amd64 make build
|
||||
GOOS=linux GOARCH=arm make build
|
||||
GOOS=linux GOARCH=arm64 make build
|
||||
GOOS=openbsd GOARCH=amd64 make build
|
||||
GOOS=freebsd GOARCH=386 make build
|
||||
GOOS=freebsd GOARCH=amd64 make build
|
||||
GOOS=windows GOARCH=amd64 make build
|
||||
GOOS=windows GOARCH=386 make build
|
||||
|
||||
plugins: binary
|
||||
GOOS=darwin GOARCH=amd64 make su3s
|
||||
GOOS=darwin GOARCH=arm64 make su3s
|
||||
GOOS=linux GOARCH=386 make su3s
|
||||
GOOS=linux GOARCH=amd64 make su3s
|
||||
GOOS=linux GOARCH=arm make su3s
|
||||
GOOS=linux GOARCH=arm64 make su3s
|
||||
GOOS=openbsd GOARCH=amd64 make su3s
|
||||
GOOS=freebsd GOARCH=386 make su3s
|
||||
GOOS=freebsd GOARCH=amd64 make su3s
|
||||
GOOS=windows GOARCH=amd64 make su3s
|
||||
GOOS=windows GOARCH=386 make su3s
|
||||
|
||||
upload-bin:
|
||||
GOOS=darwin GOARCH=amd64 make upload-single-bin
|
||||
GOOS=darwin GOARCH=arm64 make upload-single-bin
|
||||
GOOS=linux GOARCH=386 make upload-single-bin
|
||||
GOOS=linux GOARCH=amd64 make upload-single-bin
|
||||
GOOS=linux GOARCH=arm make upload-single-bin
|
||||
GOOS=linux GOARCH=arm64 make upload-single-bin
|
||||
GOOS=openbsd GOARCH=amd64 make upload-single-bin
|
||||
GOOS=freebsd GOARCH=386 make upload-single-bin
|
||||
GOOS=freebsd GOARCH=amd64 make upload-single-bin
|
||||
GOOS=windows GOARCH=amd64 make upload-single-bin
|
||||
GOOS=windows GOARCH=386 make upload-single-bin
|
||||
|
||||
rm-su3s:
|
||||
rm *.su3 -f
|
||||
|
||||
download-su3s:
|
||||
GOOS=darwin GOARCH=amd64 make download-single-su3
|
||||
GOOS=darwin GOARCH=arm64 make download-single-su3
|
||||
GOOS=linux GOARCH=386 make download-single-su3
|
||||
GOOS=linux GOARCH=amd64 make download-single-su3
|
||||
GOOS=linux GOARCH=arm make download-single-su3
|
||||
GOOS=linux GOARCH=arm64 make download-single-su3
|
||||
GOOS=openbsd GOARCH=amd64 make download-single-su3
|
||||
GOOS=freebsd GOARCH=386 make download-single-su3
|
||||
GOOS=freebsd GOARCH=amd64 make download-single-su3
|
||||
GOOS=windows GOARCH=amd64 make download-single-su3
|
||||
GOOS=windows GOARCH=386 make download-single-su3
|
||||
|
||||
upload-su3s:
|
||||
GOOS=darwin GOARCH=amd64 make upload-single-su3
|
||||
GOOS=darwin GOARCH=arm64 make upload-single-su3
|
||||
GOOS=linux GOARCH=386 make upload-single-su3
|
||||
GOOS=linux GOARCH=amd64 make upload-single-su3
|
||||
GOOS=linux GOARCH=arm make upload-single-su3
|
||||
GOOS=linux GOARCH=arm64 make upload-single-su3
|
||||
GOOS=openbsd GOARCH=amd64 make upload-single-su3
|
||||
GOOS=freebsd GOARCH=386 make upload-single-su3
|
||||
GOOS=freebsd GOARCH=amd64 make upload-single-su3
|
||||
GOOS=windows GOARCH=amd64 make upload-single-su3
|
||||
GOOS=windows GOARCH=386 make upload-single-su3
|
||||
|
||||
download-single-su3:
|
||||
wget-ds "https://github.com/eyedeekay/reseed-tools/releases/download/v$(VERSION)/reseed-tools-$(GOOS)-$(GOARCH).su3"
|
||||
|
||||
upload-single-deb:
|
||||
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools_$(VERSION)-1_amd64.deb -l "`sha256sum reseed-tools_$(VERSION)-1_amd64.deb`" -n "reseed-tools_$(VERSION)-1_amd64.deb"
|
||||
|
||||
upload-single-bin:
|
||||
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools-"$(GOOS)"-"$(GOARCH)" -l "`sha256sum reseed-tools-$(GOOS)-$(GOARCH)`" -n "reseed-tools-$(GOOS)"-"$(GOARCH)"
|
||||
|
||||
upload-single-su3:
|
||||
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools-"$(GOOS)"-"$(GOARCH).su3" -l "`sha256sum reseed-tools-$(GOOS)-$(GOARCH).su3`" -n "reseed-tools-$(GOOS)"-"$(GOARCH).su3"
|
||||
|
||||
tmp/content:
|
||||
mkdir -p tmp
|
||||
cp -rv content tmp/content
|
||||
echo "you@mail.i2p" > tmp/signer
|
||||
|
||||
tmp/lib:
|
||||
mkdir -p tmp/lib
|
||||
# cp "$(HOME)/build/shellservice.jar" tmp/lib/shellservice.jar
|
||||
|
||||
tmp/LICENSE:
|
||||
cp LICENSE.md tmp/LICENSE
|
||||
|
||||
SIGNER_DIR=$(HOME)/i2p-go-keys/
|
||||
|
||||
su3s: tmp/content tmp/lib tmp/LICENSE
|
||||
i2p.plugin.native -name=reseed-tools-$(GOOS)-$(GOARCH) \
|
||||
-signer=hankhill19580@gmail.com \
|
||||
-signer-dir=$(SIGNER_DIR) \
|
||||
-version "$(VERSION)" \
|
||||
-author=hankhill19580@gmail.com \
|
||||
-autostart=true \
|
||||
-clientname=reseed-tools-$(GOOS)-$(GOARCH) \
|
||||
-command="reseed-tools-$(GOOS)-$(GOARCH) reseed --yes --signer=\$$PLUGIN/signer --port=$(PLUGIN_PORT)" \
|
||||
-consolename="Reseed Tools" \
|
||||
-consoleurl="https://127.0.0.1:$(PLUGIN_PORT)" \
|
||||
-updateurl="http://idk.i2p/reseed-tools/reseed-tools-$(GOOS)-$(GOARCH).su3" \
|
||||
-website="http://idk.i2p/reseed-tools/" \
|
||||
-icondata="content/images/reseed-icon.png" \
|
||||
-delaystart="1" \
|
||||
-desc="`cat description-pak`" \
|
||||
-exename=reseed-tools-$(GOOS)-$(GOARCH) \
|
||||
-targetos="$(GOOS)" \
|
||||
-res=tmp/ \
|
||||
-license=MIT
|
||||
unzip -o reseed-tools-$(GOOS)-$(GOARCH).zip -d reseed-tools-$(GOOS)-$(GOARCH)-zip
|
||||
|
||||
#export sumbblinux=`sha256sum "../reseed-tools-linux.su3"`
|
||||
#export sumbbwindows=`sha256sum "../reseed-tools-windows.su3"`
|
177
README.md
177
README.md
@@ -1,98 +1,135 @@
|
||||
I2P Reseed Tools
|
||||
==================
|
||||
|
||||
This tool provides a secure and efficient reseed server for the I2P network. There are several utility commands to create, sign, and validate SU3 files.
|
||||

|
||||
|
||||
This tool provides a secure and efficient reseed server for the I2P network.
|
||||
There are several utility commands to create, sign, and validate SU3 files.
|
||||
Please note that this requires at least Go version 1.13, and uses Go Modules.
|
||||
|
||||
Standard reseeds are distributed with the I2P packages. To get your reseed
|
||||
included, apply on [zzz.i2p](http://zzz.i2p).
|
||||
|
||||
## Dependencies
|
||||
|
||||
`go`, `git`, and optionally `make` are required to build the project.
|
||||
Precompiled binaries for most platforms are available at my github mirror
|
||||
https://github.com/eyedeekay/i2p-tools-1.
|
||||
|
||||
In order to install the build-dependencies on Ubuntu or Debian, you may use:
|
||||
|
||||
```sh
|
||||
sudo apt-get install golang-go git make
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
If you have go installed you can download, build, and install this tool with `go get`
|
||||
Reseed-tools can be run as a user, as a freestanding service, or be installed
|
||||
as an I2P Plugin. It will attempt to configure itself automatically. You should
|
||||
make sure to set the `--signer` flag or the `RESEED_EMAIL` environment variable
|
||||
to configure your signing keys/contact info.
|
||||
|
||||
#### Plugin install URL's
|
||||
|
||||
Plugin releases are available inside of i2p at http://idk.i2p/reseed-tools/
|
||||
and via the github mirror at https://github.com/eyedeekay/reseed-tools/releases.
|
||||
These can be installed by adding them on the
|
||||
[http://127.0.0.1:7657/configplugins](http://127.0.0.1:7657/configplugins).
|
||||
|
||||
After installing the plugin, you should immediately edit the `$PLUGIN/signer`
|
||||
file in order to set your `--signer` email, which is used to name your keys.
|
||||
You can find the `$PLUGIN` directory in your I2P config directory, which is
|
||||
usually `$HOME/.i2p` on Unixes.
|
||||
|
||||
This will allow the developers to contact you if your reseed has issues
|
||||
and will authenticate your reseed to the I2P routers that use it.
|
||||
|
||||
- darwin/amd64: [http://idk.i2p/reseed-tools/reseed-tools-darwin-amd64.su3](http://idk.i2p/reseed-tools/reseed-tools-darwin-amd64.su3)
|
||||
- darwin/arm64: [http://idk.i2p/reseed-tools/reseed-tools-darwin-arm64.su3](http://idk.i2p/reseed-tools/reseed-tools-darwin-arm64.su3)
|
||||
- linux/386: [http://idk.i2p/reseed-tools/reseed-tools-linux-386.su3](http://idk.i2p/reseed-tools/reseed-tools-linux-386.su3)
|
||||
- linux/amd64: [http://idk.i2p/reseed-tools/reseed-tools-linux-amd64.su3](http://idk.i2p/reseed-tools/reseed-tools-linux-amd64.su3)
|
||||
- linux/arm: [http://idk.i2p/reseed-tools/reseed-tools-linux-arm.su3](http://idk.i2p/reseed-tools/reseed-tools-linux-arm.su3)
|
||||
- linux/arm64: [http://idk.i2p/reseed-tools/reseed-tools-linux-arm64.su3](http://idk.i2p/reseed-tools/reseed-tools-linux-arm64.su3)
|
||||
- openbsd/amd64: [http://idk.i2p/reseed-tools/reseed-tools-openbsd-amd64.su3](http://idk.i2p/reseed-tools/reseed-tools-openbsd-amd64.su3)
|
||||
- freebsd/386: [http://idk.i2p/reseed-tools/reseed-tools-freebsd-386.su3](http://idk.i2p/reseed-tools/reseed-tools-freebsd-386.su3)
|
||||
- freebsd/amd64: [http://idk.i2p/reseed-tools/reseed-tools-freebsd-amd64.su3](http://idk.i2p/reseed-tools/reseed-tools-freebsd-amd64.su3)
|
||||
- windows/amd64: [http://idk.i2p/reseed-tools/reseed-tools-windows-amd64.su3](http://idk.i2p/reseed-tools/reseed-tools-windows-amd64.su3)
|
||||
- windows/386: [http://idk.i2p/reseed-tools/reseed-tools-windows-386.su3](http://idk.i2p/reseed-tools/reseed-tools-windows-386.su3)
|
||||
|
||||
### Installation(From Source)
|
||||
|
||||
```
|
||||
go get github.com/MDrollette/i2p-tools
|
||||
i2p-tools -h
|
||||
git clone https://i2pgit.org/idk/reseed-tools
|
||||
cd reseed-tools
|
||||
make build
|
||||
# Optionally, if you want to install to /usr/bin/reseed-tools
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Locally behind a webserver (reverse proxy setup), preferred:
|
||||
#### Debian/Ubuntu note:
|
||||
|
||||
```
|
||||
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
|
||||
```
|
||||
Debian users who are running I2P as a system service must also run the
|
||||
`reseed-tools` as the same user. This is so that the reseed-tools can access
|
||||
the I2P service's netDb directory. On Debian and Ubuntu, that user is `i2psvc`
|
||||
and the netDb directory is: `/var/lib/i2p/i2p-config/netDb`.
|
||||
|
||||
##### Service Integration
|
||||
|
||||
Support for running as a system service as part of the reseed package
|
||||
is new. PR's that improve integration are welcome.
|
||||
|
||||
###### Systemd Service
|
||||
|
||||
A systemd service is provided which should work with the I2P Debian package
|
||||
when reseed-tools is installed in `/usr/bin/reseed-tools`. If you install with
|
||||
`make install` this service is also installed. This service will cause the
|
||||
bundles to regenerate every 12 hours.
|
||||
|
||||
The contact email for your reseed should be added in:
|
||||
`/etc/systemd/system/reseed.d/reseed.conf`.
|
||||
|
||||
Self-signed certificates will be auto-generated for these services. To change
|
||||
this you should edit the `/etc/systemd/system/reseed.d/reseed.service`.
|
||||
|
||||
- To enable starting the reseed service automatically with the system: `sudo systemctl enable reseed.service`
|
||||
- To run the service manually: `sudo sysctl start reseed.service`
|
||||
- To reload the systemd services: `sudo systemctl daemon-reload`
|
||||
- To view the status/logs: `sudo journalctl -u reseed.service`
|
||||
|
||||
###### SysV Service
|
||||
|
||||
An initscript is also provided. The initscript, unlike the systemd service,
|
||||
cannot schedule itself to restart. You should restart the service roughly once
|
||||
a day to ensure that the information does not expire.
|
||||
|
||||
The contact email for your reseed should be added in:
|
||||
`/etc/init.d/reseed`.
|
||||
|
||||
Self-signed certificates will be auto-generated for these services. To change
|
||||
this you should edit the `/etc/init.d/reseed`.
|
||||
|
||||
## Example Commands:
|
||||
|
||||
### Without a webserver, standalone with TLS support
|
||||
|
||||
```
|
||||
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
|
||||
```
|
||||
|
||||
If this is your first time running a reseed server (ie. you don't have any existing keys),
|
||||
you can simply run the command and follow the prompts to create the appropriate keys, crl and certificates.
|
||||
Afterwards an HTTPS reseed server will start on the default port and generate 6 files in your current directory
|
||||
(a TLS key, certificate and crl, and a su3-file signing key, certificate and crl).
|
||||
|
||||
Get the source code here on github or a pre-build binary anonymously on
|
||||
|
||||
http://reseed.i2p/
|
||||
http://j7xszhsjy7orrnbdys7yykrssv5imkn4eid7n5ikcnxuhpaaw6cq.b32.i2p/
|
||||
|
||||
also a short guide and complete tech info.
|
||||
|
||||
## Experimental, currently only available from eyedeekay/i2p-tools-1 fork
|
||||
|
||||
Requires ```go mod``` and at least go 1.13. To build the eyedeekay/i2p-tools-1
|
||||
fork, from anywhere:
|
||||
|
||||
git clone https://github.com/eyedeekay/i2p-tools-1
|
||||
cd i2p-tools-1
|
||||
make build
|
||||
|
||||
### Without a webserver, standalone, self-supervising(Automatic restarts)
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --restart=start
|
||||
reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, automatic OnionV3 with TLS support
|
||||
### Locally behind a webserver (reverse proxy setup), preferred:
|
||||
|
||||
If you are using a reverse proxy server it may provide the TLS certificate instead.
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
|
||||
reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, serve P2P with LibP2P
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, upload a single signed .su3 to github
|
||||
|
||||
* This one isn't working yet, look for it by ~Monday.
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=i2p-tools-1 --ghuser=eyedeekay
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, in-network reseed
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, and LibP2P
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p
|
||||
```
|
||||
|
||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, I2P In-Network reseed, and LibP2P, self-supervising
|
||||
|
||||
```
|
||||
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --restart=start
|
||||
```
|
||||
- **Usage** [More examples can be found here.](EXAMPLES.md)
|
||||
- **Docker** [Docker examples can be found here](DOCKER.md)
|
||||
|
12
cmd/i2pd.go
Normal file
12
cmd/i2pd.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build i2pd
|
||||
// +build i2pd
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
i2pd "github.com/eyedeekay/go-i2pd/goi2pd"
|
||||
)
|
||||
|
||||
func InitializeI2PD() func() {
|
||||
return i2pd.InitI2PSAM(nil)
|
||||
}
|
@@ -3,7 +3,7 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func NewKeygenCommand() cli.Command {
|
||||
@@ -27,6 +27,7 @@ func NewKeygenCommand() cli.Command {
|
||||
func keygenAction(c *cli.Context) {
|
||||
signerID := c.String("signer")
|
||||
tlsHost := c.String("tlsHost")
|
||||
trustProxy := c.Bool("trustProxy")
|
||||
|
||||
if signerID == "" && tlsHost == "" {
|
||||
fmt.Println("You must specify either --tlsHost or --signer")
|
||||
@@ -40,10 +41,12 @@ func keygenAction(c *cli.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
if tlsHost != "" {
|
||||
if err := createTLSCertificate(tlsHost); nil != err {
|
||||
fmt.Println(err)
|
||||
return
|
||||
if trustProxy {
|
||||
if tlsHost != "" {
|
||||
if err := createTLSCertificate(tlsHost); nil != err {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
308
cmd/reseed.go
308
cmd/reseed.go
@@ -2,6 +2,9 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
//"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -11,19 +14,44 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"crawshaw.io/littleboss"
|
||||
"github.com/MDrollette/i2p-tools/reseed"
|
||||
"github.com/RTradeLtd/go-garlic-tcp-transport/common"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/cretz/bine/tor"
|
||||
"github.com/cretz/bine/torutil"
|
||||
"github.com/cretz/bine/torutil/ed25519"
|
||||
"github.com/eyedeekay/sam3"
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
"github.com/urfave/cli"
|
||||
"i2pgit.org/idk/reseed-tools/reseed"
|
||||
|
||||
"github.com/eyedeekay/checki2cp/getmeanetdb"
|
||||
)
|
||||
|
||||
func getDefaultSigner() string {
|
||||
intentionalsigner := os.Getenv("RESEED_EMAIL")
|
||||
if intentionalsigner == "" {
|
||||
adminsigner := os.Getenv("MAILTO")
|
||||
if adminsigner != "" {
|
||||
return strings.Replace(adminsigner, "\n", "", -1)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return strings.Replace(intentionalsigner, "\n", "", -1)
|
||||
}
|
||||
|
||||
func getHostName() string {
|
||||
hostname := os.Getenv("RESEED_HOSTNAME")
|
||||
if hostname == "" {
|
||||
hostname, _ = os.Hostname()
|
||||
}
|
||||
return strings.Replace(hostname, "\n", "", -1)
|
||||
}
|
||||
|
||||
func NewReseedCommand() cli.Command {
|
||||
ndb, err := getmeanetdb.WhereIstheNetDB()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return cli.Command{
|
||||
Name: "reseed",
|
||||
Usage: "Start a reseed server",
|
||||
@@ -31,10 +59,12 @@ func NewReseedCommand() cli.Command {
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "signer",
|
||||
Value: getDefaultSigner(),
|
||||
Usage: "Your su3 signing ID (ex. something@mail.i2p)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tlsHost",
|
||||
Value: getHostName(),
|
||||
Usage: "The public hostname used on your TLS certificate",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
@@ -56,6 +86,7 @@ func NewReseedCommand() cli.Command {
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "netdb",
|
||||
Value: ndb,
|
||||
Usage: "Path to NetDB directory containing routerInfos",
|
||||
},
|
||||
cli.StringFlag{
|
||||
@@ -83,7 +114,7 @@ func NewReseedCommand() cli.Command {
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "numSu3",
|
||||
Value: 0,
|
||||
Value: 50,
|
||||
Usage: "Number of su3 files to build (0 = automatic based on size of netdb)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
@@ -118,31 +149,93 @@ func NewReseedCommand() cli.Command {
|
||||
Name: "i2p",
|
||||
Usage: "Listen for reseed request inside the I2P network",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "yes",
|
||||
Usage: "Automatically answer 'yes' to self-signed SSL generation",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "samaddr",
|
||||
Value: "127.0.0.1:7656",
|
||||
Usage: "Use this SAM address to set up I2P connections for in-network reseed",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "acme",
|
||||
Usage: "Automatically generate a TLS certificate with the ACME protocol, defaults to Let's Encrypt",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "restart",
|
||||
Value: "start",
|
||||
Usage: "Start in self-supervising mode",
|
||||
Name: "acmeserver",
|
||||
Value: "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||
Usage: "Use this server to issue a certificate with the ACME protocol",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "yggdrasil",
|
||||
Usage: "Listen on the the Yggdrasil network to provide an alternate reseed",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "yggconfig",
|
||||
Value: "yggdrasil.conf",
|
||||
Usage: "Path to the Yggdrasil configuration file",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func reseedMain(c *cli.Context) {
|
||||
lb := littleboss.New("reseed")
|
||||
restart := c.String("restart")
|
||||
lb.Command("restart", &restart)
|
||||
lb.Run(func(ctx context.Context) {
|
||||
reseedAction(c)
|
||||
})
|
||||
func CreateEepServiceKey(c *cli.Context) (i2pkeys.I2PKeys, error) {
|
||||
sam, err := sam3.NewSAM(c.String("samaddr"))
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
defer sam.Close()
|
||||
k, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
return k, err
|
||||
}
|
||||
|
||||
func LoadKeys(keysPath string, c *cli.Context) (i2pkeys.I2PKeys, error) {
|
||||
if _, err := os.Stat(keysPath); os.IsNotExist(err) {
|
||||
keys, err := CreateEepServiceKey(c)
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
file, err := os.Create(keysPath)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
err = i2pkeys.StoreKeysIncompat(keys, file)
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
return keys, nil
|
||||
} else if err == nil {
|
||||
file, err := os.Open(keysPath)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
keys, err := i2pkeys.LoadKeysIncompat(file)
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
return keys, nil
|
||||
} else {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// fileExists checks if a file exists and is not a directory before we
|
||||
// try using it to prevent further errors.
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
func reseedAction(c *cli.Context) {
|
||||
// validate flags
|
||||
netdbDir := c.String("netdb")
|
||||
if netdbDir == "" {
|
||||
fmt.Println("--netdb is required")
|
||||
@@ -150,10 +243,22 @@ func reseedAction(c *cli.Context) {
|
||||
}
|
||||
|
||||
signerID := c.String("signer")
|
||||
if signerID == "" {
|
||||
if signerID == "" || signerID == "you@mail.i2p" {
|
||||
fmt.Println("--signer is required")
|
||||
return
|
||||
}
|
||||
if !strings.Contains(signerID, "@") {
|
||||
if !fileExists(signerID) {
|
||||
fmt.Println("--signer must be an email address or a file containing an email address.")
|
||||
return
|
||||
}
|
||||
bytes, err := ioutil.ReadFile(signerID)
|
||||
if err != nil {
|
||||
fmt.Println("--signer must be an email address or a file containing an email address.")
|
||||
return
|
||||
}
|
||||
signerID = string(bytes)
|
||||
}
|
||||
|
||||
var tlsCert, tlsKey string
|
||||
tlsHost := c.String("tlsHost")
|
||||
@@ -163,30 +268,75 @@ func reseedAction(c *cli.Context) {
|
||||
var i2pTlsCert, i2pTlsKey string
|
||||
var i2pkey i2pkeys.I2PKeys
|
||||
|
||||
if tlsHost != "" {
|
||||
onionTlsHost = tlsHost
|
||||
i2pTlsHost = tlsHost
|
||||
tlsKey = c.String("tlsKey")
|
||||
// if no key is specified, default to the host.pem in the current dir
|
||||
if tlsKey == "" {
|
||||
tlsKey = tlsHost + ".pem"
|
||||
onionTlsKey = tlsHost + ".pem"
|
||||
i2pTlsKey = tlsHost + ".pem"
|
||||
}
|
||||
|
||||
tlsCert = c.String("tlsCert")
|
||||
// if no certificate is specified, default to the host.crt in the current dir
|
||||
if tlsCert == "" {
|
||||
tlsCert = tlsHost + ".crt"
|
||||
onionTlsCert = tlsHost + ".crt"
|
||||
i2pTlsCert = tlsHost + ".crt"
|
||||
}
|
||||
|
||||
// prompt to create tls keys if they don't exist?
|
||||
auto := c.Bool("yes")
|
||||
ignore := c.Bool("ignore")
|
||||
if !ignore {
|
||||
// use ACME?
|
||||
acme := c.Bool("acme")
|
||||
if acme {
|
||||
acmeserver := c.String("acmeserver")
|
||||
err := checkUseAcmeCert(tlsHost, signerID, acmeserver, &tlsCert, &tlsKey, auto)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
err := checkOrNewTLSCert(tlsHost, &tlsCert, &tlsKey, auto)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if c.Bool("i2p") {
|
||||
var err error
|
||||
i2pkey, err = i2phelpers.LoadKeys("i2pkeys")
|
||||
i2pkey, err = LoadKeys("reseed.i2pkeys", c)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
i2pTlsHost = i2pkey.Addr().Base32()
|
||||
if i2pTlsHost == "" {
|
||||
i2pTlsHost = i2pkey.Addr().Base32()
|
||||
}
|
||||
if i2pTlsHost != "" {
|
||||
i2pTlsKey = c.String("tlsKey")
|
||||
// if no key is specified, default to the host.pem in the current dir
|
||||
if i2pTlsKey == "" {
|
||||
i2pTlsKey = i2pTlsHost + ".pem"
|
||||
}
|
||||
|
||||
i2pTlsCert = c.String("tlsCert")
|
||||
// if no certificate is specified, default to the host.crt in the current dir
|
||||
if i2pTlsCert == "" {
|
||||
i2pTlsCert = i2pTlsHost + ".crt"
|
||||
}
|
||||
|
||||
// prompt to create tls keys if they don't exist?
|
||||
err := checkOrNewTLSCert(i2pTlsHost, &i2pTlsCert, &i2pTlsKey)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
auto := c.Bool("yes")
|
||||
ignore := c.Bool("trustProxy")
|
||||
if !ignore {
|
||||
err := checkOrNewTLSCert(i2pTlsHost, &i2pTlsCert, &i2pTlsKey, auto)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,52 +356,36 @@ func reseedAction(c *cli.Context) {
|
||||
}
|
||||
ok = []byte(key.PrivateKey())
|
||||
}
|
||||
onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
|
||||
if onionTlsHost == "" {
|
||||
onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
|
||||
}
|
||||
err = ioutil.WriteFile(c.String("onionKey"), ok, 0644)
|
||||
if err != nil {
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
if onionTlsHost != "" {
|
||||
onionTlsKey = c.String("tlsKey")
|
||||
// if no key is specified, default to the host.pem in the current dir
|
||||
if onionTlsKey == "" {
|
||||
onionTlsKey = onionTlsHost + ".pem"
|
||||
}
|
||||
|
||||
onionTlsCert = c.String("tlsCert")
|
||||
// if no certificate is specified, default to the host.crt in the current dir
|
||||
if onionTlsCert == "" {
|
||||
onionTlsCert = onionTlsHost + ".crt"
|
||||
}
|
||||
|
||||
// prompt to create tls keys if they don't exist?
|
||||
err := checkOrNewTLSCert(onionTlsHost, &onionTlsCert, &onionTlsKey)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
auto := c.Bool("yes")
|
||||
ignore := c.Bool("trustProxy")
|
||||
if !ignore {
|
||||
err := checkOrNewTLSCert(onionTlsHost, &onionTlsCert, &onionTlsKey, auto)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tlsHost != "" {
|
||||
tlsKey = c.String("tlsKey")
|
||||
// if no key is specified, default to the host.pem in the current dir
|
||||
if tlsKey == "" {
|
||||
tlsKey = tlsHost + ".pem"
|
||||
}
|
||||
|
||||
tlsCert = c.String("tlsCert")
|
||||
// if no certificate is specified, default to the host.crt in the current dir
|
||||
if tlsCert == "" {
|
||||
tlsCert = tlsHost + ".crt"
|
||||
}
|
||||
|
||||
// prompt to create tls keys if they don't exist?
|
||||
err := checkOrNewTLSCert(tlsHost, &tlsCert, &tlsKey)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
reloadIntvl, err := time.ParseDuration(c.String("interval"))
|
||||
if nil != err {
|
||||
fmt.Printf("'%s' is not a valid time interval.\n", reloadIntvl)
|
||||
@@ -265,7 +399,8 @@ func reseedAction(c *cli.Context) {
|
||||
}
|
||||
|
||||
// load our signing privKey
|
||||
privKey, err := getOrNewSigningCert(&signerKey, signerID)
|
||||
auto := c.Bool("yes")
|
||||
privKey, err := getOrNewSigningCert(&signerKey, signerID, auto)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
@@ -308,7 +443,15 @@ func reseedAction(c *cli.Context) {
|
||||
reseedP2P(c, reseeder)
|
||||
}
|
||||
}
|
||||
if tlsHost != "" && tlsCert != "" && tlsKey != "" {
|
||||
if c.Bool("yggdrasil") {
|
||||
log.Printf("Yggdrasil listener starting\n")
|
||||
if tlsHost != "" && tlsCert != "" && tlsKey != "" {
|
||||
go reseedYggdrasil(c, reseeder)
|
||||
} else {
|
||||
reseedYggdrasil(c, reseeder)
|
||||
}
|
||||
}
|
||||
if !c.Bool("trustProxy") {
|
||||
log.Printf("HTTPS server starting\n")
|
||||
reseedHTTPS(c, tlsCert, tlsKey, reseeder)
|
||||
} else {
|
||||
@@ -317,7 +460,7 @@ func reseedAction(c *cli.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder reseed.Reseeder) {
|
||||
func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
@@ -346,7 +489,7 @@ func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder reseed.Reseede
|
||||
}
|
||||
}
|
||||
|
||||
func reseedHTTP(c *cli.Context, reseeder reseed.Reseeder) {
|
||||
func reseedHTTP(c *cli.Context, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
@@ -383,7 +526,36 @@ func makeRandomHost(port int) (host.Host, error) {
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func reseedP2P(c *cli.Context, reseeder reseed.Reseeder) {
|
||||
func reseedYggdrasil(c *cli.Context, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
server.YggdrasilConf = c.String("yggconfig")
|
||||
// load a blacklist
|
||||
blacklist := reseed.NewBlacklist()
|
||||
server.Blacklist = blacklist
|
||||
blacklistFile := c.String("blacklist")
|
||||
if "" != blacklistFile {
|
||||
blacklist.LoadFile(blacklistFile)
|
||||
}
|
||||
|
||||
// print stats once in a while
|
||||
if c.Duration("stats") != 0 {
|
||||
go func() {
|
||||
var mem runtime.MemStats
|
||||
for range time.Tick(c.Duration("stats")) {
|
||||
runtime.ReadMemStats(&mem)
|
||||
log.Printf("TotalAllocs: %d Kb, Allocs: %d Kb, Mallocs: %d, NumGC: %d", mem.TotalAlloc/1024, mem.Alloc/1024, mem.Mallocs, mem.NumGC)
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err := server.ListenAndServeYggdrasil(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Printf("Yggdrasil listener started on %s\n", server.YggdrasilAddr())
|
||||
}
|
||||
|
||||
func reseedP2P(c *cli.Context, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
@@ -421,7 +593,7 @@ func reseedP2P(c *cli.Context, reseeder reseed.Reseeder) {
|
||||
}
|
||||
}
|
||||
|
||||
func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder reseed.Reseeder) {
|
||||
func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
@@ -496,7 +668,7 @@ func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder rese
|
||||
log.Printf("Onion server started on %s\n", server.Addr)
|
||||
}
|
||||
|
||||
func reseedI2P(c *cli.Context, i2pTlsCert, i2pTlsKey string, i2pIdentKey i2pkeys.I2PKeys, reseeder reseed.Reseeder) {
|
||||
func reseedI2P(c *cli.Context, i2pTlsCert, i2pTlsKey string, i2pIdentKey i2pkeys.I2PKeys, reseeder *reseed.ReseederImpl) {
|
||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||
server.Reseeder = reseeder
|
||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||
@@ -524,26 +696,16 @@ func reseedI2P(c *cli.Context, i2pTlsCert, i2pTlsKey string, i2pIdentKey i2pkeys
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
port += 1
|
||||
if _, err := os.Stat(c.String("onionKey")); err == nil {
|
||||
//ok, err := ioutil.ReadFile(c.String("onionKey"))
|
||||
if err != nil {
|
||||
log.Fatalln(err.Error())
|
||||
} else {
|
||||
if i2pTlsCert != "" && i2pTlsKey != "" {
|
||||
if err := server.ListenAndServeI2PTLS(c.String("samaddr"), i2pIdentKey, i2pTlsCert, i2pTlsKey); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
if err := server.ListenAndServeI2P(c.String("samaddr"), i2pIdentKey); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
}
|
||||
if i2pTlsCert != "" && i2pTlsKey != "" {
|
||||
if err := server.ListenAndServeI2PTLS(c.String("samaddr"), i2pIdentKey, i2pTlsCert, i2pTlsKey); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
} else if os.IsNotExist(err) {
|
||||
} else {
|
||||
if err := server.ListenAndServeI2P(c.String("samaddr"), i2pIdentKey); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.Printf("Onion server started on %s\n", server.Addr)
|
||||
}
|
||||
|
222
cmd/utils.go
222
cmd/utils.go
@@ -2,10 +2,12 @@ package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
@@ -16,8 +18,15 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/MDrollette/i2p-tools/reseed"
|
||||
"github.com/MDrollette/i2p-tools/su3"
|
||||
"i2pgit.org/idk/reseed-tools/reseed"
|
||||
"i2pgit.org/idk/reseed-tools/su3"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge/http01"
|
||||
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
)
|
||||
|
||||
func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
|
||||
@@ -35,18 +44,38 @@ func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
|
||||
return privKey, nil
|
||||
}
|
||||
|
||||
// Taken directly from the lego example, since we need very minimal support
|
||||
// https://go-acme.github.io/lego/usage/library/
|
||||
type MyUser struct {
|
||||
Email string
|
||||
Registration *registration.Resource
|
||||
key crypto.PrivateKey
|
||||
}
|
||||
|
||||
func (u *MyUser) GetEmail() string {
|
||||
return u.Email
|
||||
}
|
||||
func (u MyUser) GetRegistration() *registration.Resource {
|
||||
return u.Registration
|
||||
}
|
||||
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
||||
return u.key
|
||||
}
|
||||
|
||||
func signerFile(signerID string) string {
|
||||
return strings.Replace(signerID, "@", "_at_", 1)
|
||||
}
|
||||
|
||||
func getOrNewSigningCert(signerKey *string, signerID string) (*rsa.PrivateKey, error) {
|
||||
func getOrNewSigningCert(signerKey *string, signerID string, auto bool) (*rsa.PrivateKey, error) {
|
||||
if _, err := os.Stat(*signerKey); nil != err {
|
||||
fmt.Printf("Unable to read signing key '%s'\n", *signerKey)
|
||||
fmt.Printf("Would you like to generate a new signing key for %s? (y or n): ", signerID)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
if []byte(input)[0] != 'y' {
|
||||
return nil, fmt.Errorf("A signing key is required")
|
||||
if !auto {
|
||||
fmt.Printf("Would you like to generate a new signing key for %s? (y or n): ", signerID)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
if []byte(input)[0] != 'y' {
|
||||
return nil, fmt.Errorf("A signing key is required")
|
||||
}
|
||||
}
|
||||
if err := createSigningCertificate(signerID); nil != err {
|
||||
return nil, err
|
||||
@@ -58,7 +87,7 @@ func getOrNewSigningCert(signerKey *string, signerID string) (*rsa.PrivateKey, e
|
||||
return loadPrivateKey(*signerKey)
|
||||
}
|
||||
|
||||
func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string) error {
|
||||
func checkUseAcmeCert(tlsHost, signer, cadirurl string, tlsCert, tlsKey *string, auto bool) error {
|
||||
_, certErr := os.Stat(*tlsCert)
|
||||
_, keyErr := os.Stat(*tlsKey)
|
||||
if certErr != nil || keyErr != nil {
|
||||
@@ -69,13 +98,174 @@ func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string) error {
|
||||
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
|
||||
}
|
||||
|
||||
fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
if []byte(input)[0] != 'y' {
|
||||
fmt.Println("Continuing without TLS")
|
||||
if !auto {
|
||||
fmt.Printf("Would you like to generate a new certificate with Let's Encrypt or a custom ACME server? '%s'? (y or n): ", tlsHost)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
if []byte(input)[0] != 'y' {
|
||||
fmt.Println("Continuing without TLS")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TLSConfig := &tls.Config{}
|
||||
TLSConfig.NextProtos = []string{"http/1.1"}
|
||||
TLSConfig.Certificates = make([]tls.Certificate, 1)
|
||||
var err error
|
||||
TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(*tlsCert, *tlsKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if time.Now().Sub(TLSConfig.Certificates[0].Leaf.NotAfter) < (time.Hour * 48) {
|
||||
ecder, err := ioutil.ReadFile(tlsHost + signer + ".acme.key")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
privateKey, err := x509.ParseECPrivateKey(ecder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user := MyUser{
|
||||
Email: signer,
|
||||
key: privateKey,
|
||||
}
|
||||
config := lego.NewConfig(&user)
|
||||
config.CADirURL = cadirurl
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
renewAcmeIssuedCert(client, user, tlsHost, tlsCert, tlsKey)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ecder, err := x509.MarshalECPrivateKey(privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename := tlsHost + signer + ".acme.key"
|
||||
keypem, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer keypem.Close()
|
||||
err = pem.Encode(keypem, &pem.Block{Type: "EC PRIVATE KEY", Bytes: ecder})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user := MyUser{
|
||||
Email: signer,
|
||||
key: privateKey,
|
||||
}
|
||||
config := lego.NewConfig(&user)
|
||||
config.CADirURL = cadirurl
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return newAcmeIssuedCert(client, user, tlsHost, tlsCert, tlsKey)
|
||||
}
|
||||
|
||||
func renewAcmeIssuedCert(client *lego.Client, user MyUser, tlsHost string, tlsCert, tlsKey *string) error {
|
||||
var err error
|
||||
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "8000"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "8443"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// New users will need to register
|
||||
if user.Registration, err = client.Registration.QueryRegistration(); err != nil {
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Registration = reg
|
||||
}
|
||||
resource, err := client.Certificate.Get(tlsHost, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certificates, err := client.Certificate.Renew(*resource, true, false, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ioutil.WriteFile(tlsHost+".pem", certificates.PrivateKey, 0600)
|
||||
ioutil.WriteFile(tlsHost+".crt", certificates.Certificate, 0600)
|
||||
// ioutil.WriteFile(tlsHost+".crl", certificates.PrivateKey, 0600)
|
||||
*tlsCert = tlsHost + ".crt"
|
||||
*tlsKey = tlsHost + ".pem"
|
||||
return nil
|
||||
}
|
||||
|
||||
func newAcmeIssuedCert(client *lego.Client, user MyUser, tlsHost string, tlsCert, tlsKey *string) error {
|
||||
var err error
|
||||
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "8000"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "8443"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// New users will need to register
|
||||
if user.Registration, err = client.Registration.QueryRegistration(); err != nil {
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Registration = reg
|
||||
}
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{tlsHost},
|
||||
Bundle: true,
|
||||
}
|
||||
certificates, err := client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ioutil.WriteFile(tlsHost+".pem", certificates.PrivateKey, 0600)
|
||||
ioutil.WriteFile(tlsHost+".crt", certificates.Certificate, 0600)
|
||||
// ioutil.WriteFile(tlsHost+".crl", certificates.PrivateKey, 0600)
|
||||
*tlsCert = tlsHost + ".crt"
|
||||
*tlsKey = tlsHost + ".pem"
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error {
|
||||
_, certErr := os.Stat(*tlsCert)
|
||||
_, keyErr := os.Stat(*tlsKey)
|
||||
if certErr != nil || keyErr != nil {
|
||||
if certErr != nil {
|
||||
fmt.Printf("Unable to read TLS certificate '%s'\n", *tlsCert)
|
||||
}
|
||||
if keyErr != nil {
|
||||
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
|
||||
}
|
||||
|
||||
if !auto {
|
||||
fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
if []byte(input)[0] != 'y' {
|
||||
fmt.Println("Continuing without TLS")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := createTLSCertificate(tlsHost); nil != err {
|
||||
return err
|
||||
@@ -157,6 +347,10 @@ func createSigningCertificate(signerID string) error {
|
||||
}
|
||||
|
||||
func createTLSCertificate(host string) error {
|
||||
return CreateTLSCertificate(host)
|
||||
}
|
||||
|
||||
func CreateTLSCertificate(host string) error {
|
||||
fmt.Println("Generating TLS keys. This may take a minute...")
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
if err != nil {
|
||||
|
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/MDrollette/i2p-tools/reseed"
|
||||
"github.com/MDrollette/i2p-tools/su3"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/urfave/cli"
|
||||
"i2pgit.org/idk/reseed-tools/reseed"
|
||||
"i2pgit.org/idk/reseed-tools/su3"
|
||||
)
|
||||
|
||||
func NewSu3VerifyCommand() cli.Command {
|
||||
|
BIN
content/images/reseed-icon.png
Normal file
BIN
content/images/reseed-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
content/images/reseed.png
Normal file
BIN
content/images/reseed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
10
content/index.html
Normal file
10
content/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<h1 id="you-have-found-an-i2p-reseed">You have found an I2P Reseed</h1>
|
||||
<p>Maybe it was by accident, or maybe you visited the URL because you saw it in the software somewhere. While we’ve got your attention, we’re going to take this opportunity to tell you a little about what we do here. I2P is a peer-to-peer network which uses “Garlic Routing” to maintain privacy. Reseed nodes help you get connected to I2P for the first time, and even though you should only have to use them once in a great while, they are very important services.</p>
|
||||
<h2 id="to-learn-more-about-i2p-visit"><a href="https://geti2p.net">To learn more about I2P, visit</a></h2>
|
||||
<p><a href="https://geti2p.net"><img src="images/reseed.png" alt="Help reseed" /></a></p>
|
||||
<ul>
|
||||
<li><a href="https://geti2p.net/en/docs/reseed">Learn more about reseeds here:</a></li>
|
||||
<li><a href="https://geti2p.net/en/get-involved/guides/reseed">Learn how to run a reseed here:</a></li>
|
||||
<li><a href="https://i2pgit.org/idk/reseed-tools">Read the reseed server code and learn about more reseed options here:</a></li>
|
||||
</ul>
|
||||
<p>Here on purpose? Here’s a one-time link to a reseed bundle for you.</p>
|
18
content/lang/ar/homepage.md
Normal file
18
content/lang/ar/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
هذا هو خادم I2P Reseed
|
||||
=============================
|
||||
|
||||
I2P هي شبكة نظير إلى نظير تستخدم "توجيه الثوم" للحفاظ على الخصوصية.
|
||||
تساعدك عقد Reseed على الاتصال بـ I2P لأول مرة ، وعلى الرغم من ذلك
|
||||
يجب عليك فقط استخدامها مرة واحدة كل فترة ، فهي مهمة جدًا
|
||||
خدمات.
|
||||
|
||||
[لمزيد من المعلومات حول I2P ، قم بزيارة موقع المشروع] (https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[! [إعادة المساعدة] (images / reseed.png)] (https://geti2p.net)
|
||||
|
||||
- [مزيد من المعلومات حول عمليات إعادة التوريد] (https://geti2p.net/en/docs/reseed)
|
||||
- [تعرف على كيفية تشغيل Reseed] (https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [اقرأ رمز خادم إعادة التزويد وتعرّف على المزيد من خيارات إعادة التزويد] (https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### هل لديك مشاكل في الاتصال؟ إليك رابط لمرة واحدة لحزمة إعادة إرسال لك.
|
18
content/lang/bn/homepage.md
Normal file
18
content/lang/bn/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
এটি একটি I2P রিসিড সার্ভার
|
||||
============================
|
||||
|
||||
I2P হল একটি পিয়ার-টু-পিয়ার নেটওয়ার্ক যা গোপনীয়তা বজায় রাখতে "গার্লিক রাউটিং" ব্যবহার করে।
|
||||
রিসিড নোড আপনাকে প্রথমবার I2P এর সাথে সংযুক্ত হতে সাহায্য করে, এবং যদিও
|
||||
আপনি শুধুমাত্র একটি মহান সময়ের মধ্যে একবার তাদের ব্যবহার করা উচিত, তারা খুবই গুরুত্বপূর্ণ
|
||||
সেবা.
|
||||
|
||||
[I2P সম্পর্কে আরও জানতে, প্রকল্পের ওয়েবসাইট দেখুন](https://geti2p.net)
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [রিসিড সম্পর্কে আরও জানুন](https://geti2p.net/en/docs/reseed)
|
||||
- [কিভাবে রিসিড চালাতে হয় তা জানুন](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [রিসিড সার্ভার কোড পড়ুন এবং আরও রিসিড বিকল্প সম্পর্কে জানুন](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### সংযোগ সমস্যা হচ্ছে? এখানে আপনার জন্য একটি রিসিড বান্ডেলের একটি এককালীন লিঙ্ক রয়েছে৷
|
18
content/lang/de/homepage.md
Normal file
18
content/lang/de/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Dies ist ein I2P-Reseed-Server
|
||||
============================
|
||||
|
||||
I2P ist ein Peer-to-Peer-Netzwerk, das „Garlic Routing“ verwendet, um die Privatsphäre zu wahren.
|
||||
Reseed-Knoten helfen Ihnen, zum ersten Mal mit I2P verbunden zu werden, und das obwohl
|
||||
Sie sollten sie nur ab und zu verwenden müssen, sie sind sehr wichtig
|
||||
Dienstleistungen.
|
||||
|
||||
[Um mehr über I2P zu erfahren, besuchen Sie die Projektwebsite](https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [Erfahren Sie mehr über Reseeds](https://geti2p.net/en/docs/reseed)
|
||||
- [Erfahren Sie, wie Sie einen Reseed ausführen](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Lesen Sie den Re-Seed-Server-Code und erfahren Sie mehr über Re-Seed-Optionen](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Haben Sie Verbindungsprobleme? Hier ist ein einmaliger Link zu einem Re-Seed-Bundle für Sie.
|
18
content/lang/en/homepage.md
Normal file
18
content/lang/en/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
This is an I2P Reseed Server
|
||||
============================
|
||||
|
||||
I2P is a peer-to-peer network which uses “Garlic Routing” to maintain privacy.
|
||||
Reseed nodes help you get connected to I2P for the first time, and even though
|
||||
you should only have to use them once in a great while, they are very important
|
||||
services.
|
||||
|
||||
[To learn more about I2P, visit the project website](https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [Learn more about reseeds](https://geti2p.net/en/docs/reseed)
|
||||
- [Learn how to run a reseed](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Read the reseed server code and learn about more reseed options](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Having connection issues? Here is a one-time link to a reseed bundle for you.
|
18
content/lang/es/homepage.md
Normal file
18
content/lang/es/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Este es un servidor de reinicio I2P
|
||||
============================
|
||||
|
||||
I2P es una red de igual a igual que utiliza "Enrutamiento de ajo" para mantener la privacidad.
|
||||
Los nodos de reseed le ayudan a conectarse a I2P por primera vez, y aunque
|
||||
solo debería tener que usarlos de vez en cuando, son muy importantes
|
||||
servicios.
|
||||
|
||||
[Para obtener más información sobre I2P, visite el sitio web del proyecto] (https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[! [Help reseed] (images / reseed.png)] (https://geti2p.net)
|
||||
|
||||
- [Obtenga más información sobre reseeds] (https://geti2p.net/en/docs/reseed)
|
||||
- [Aprenda a ejecutar un reseed] (https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Lea el código del servidor reseed y conozca más opciones de reseed] (https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### ¿Tienes problemas de conexión? Aquí hay un enlace único a un paquete reseed para usted.
|
18
content/lang/fr/homepage.md
Normal file
18
content/lang/fr/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Ceci est un serveur de réensemencement I2P
|
||||
============================
|
||||
|
||||
I2P est un réseau peer-to-peer qui utilise le « routage à l'ail » pour maintenir la confidentialité.
|
||||
Les nœuds de réamorçage vous aident à vous connecter à I2P pour la première fois, et même si
|
||||
vous ne devriez avoir à les utiliser qu'une fois de temps en temps, ils sont très importants
|
||||
prestations de service.
|
||||
|
||||
[Pour en savoir plus sur I2P, visitez le site Web du projet](https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [En savoir plus sur les réensemencements](https://geti2p.net/en/docs/reseed)
|
||||
- [Apprenez à exécuter un reseed](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Lire le code du serveur de réensemencement et en savoir plus sur les options de réensemencement] (https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Vous avez des problèmes de connexion ? Voici un lien unique vers un paquet de graines pour vous.
|
18
content/lang/hi/homepage.md
Normal file
18
content/lang/hi/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
यह एक I2P शोधित सर्वर है
|
||||
===========================
|
||||
|
||||
I2P एक पीयर-टू-पीयर नेटवर्क है जो गोपनीयता बनाए रखने के लिए "लहसुन रूटिंग" का उपयोग करता है।
|
||||
रीसेड नोड्स आपको पहली बार I2P से कनेक्ट होने में मदद करते हैं, और भले ही
|
||||
आपको उन्हें केवल एक बार ही उपयोग करना चाहिए, वे बहुत महत्वपूर्ण हैं
|
||||
सेवाएं।
|
||||
|
||||
[I2P के बारे में अधिक जानने के लिए, प्रोजेक्ट वेबसाइट पर जाएँ](https://geti2p.net)
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [रिसेड्स के बारे में और जानें](https://geti2p.net/hi/docs/reseed)
|
||||
- [रिसेड चलाना सीखें](https://geti2p.net/hi/get-involved/guides/reseed)
|
||||
- [रीडेड सर्वर कोड पढ़ें और अधिक शोध विकल्पों के बारे में जानें](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### कनेक्शन की समस्या आ रही है? यहां आपके लिए एक शोधित बंडल का वन-टाइम लिंक दिया गया है।
|
18
content/lang/id/homepage.md
Normal file
18
content/lang/id/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Ini adalah Server Reseed I2P
|
||||
==============================
|
||||
|
||||
I2P adalah jaringan peer-to-peer yang menggunakan "Garlic Routing" untuk menjaga privasi.
|
||||
Reseed node membantu Anda terhubung ke I2P untuk pertama kalinya, dan meskipun
|
||||
Anda hanya perlu menggunakannya sesekali, itu sangat penting
|
||||
jasa.
|
||||
|
||||
[Untuk mempelajari lebih lanjut tentang I2P, kunjungi situs web proyek](https://geti2p.net)
|
||||
-------------------------------------------------- -----------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [Pelajari lebih lanjut tentang reseed](https://geti2p.net/en/docs/reseed)
|
||||
- [Pelajari cara menjalankan reseed](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Baca kode server reseed dan pelajari tentang opsi reseed lainnya](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Mengalami masalah koneksi? Berikut ini tautan satu kali ke bundel reseed untuk Anda.
|
18
content/lang/jp/homepage.md
Normal file
18
content/lang/jp/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
これはI2PReseedServerです
|
||||
============================
|
||||
|
||||
I2Pは、プライバシーを維持するために「GarlicRouting」を使用するピアツーピアネットワークです。
|
||||
再シードノードは、I2Pに初めて接続するのに役立ちます。
|
||||
たまに一度だけ使用する必要があります、それらは非常に重要です
|
||||
サービス。
|
||||
|
||||
[I2Pの詳細については、プロジェクトのWebサイトにアクセスしてください](https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
-[再シードの詳細](https://geti2p.net/en/docs/reseed)
|
||||
-[再シードの実行方法を学ぶ](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
-[再シードサーバーコードを読み、再シードオプションの詳細を確認してください](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
###接続に問題がありますか? これがあなたのための再シードバンドルへのワンタイムリンクです。
|
18
content/lang/ko/homepage.md
Normal file
18
content/lang/ko/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
I2P Reseed 서버입니다.
|
||||
==============================
|
||||
|
||||
I2P는 "Garlic Routing"을 사용하여 개인 정보를 유지하는 P2P 네트워크입니다.
|
||||
Reseed 노드는 처음으로 I2P에 연결하는 데 도움이 됩니다.
|
||||
아주 가끔은 한 번만 사용해야 하므로 매우 중요합니다.
|
||||
서비스.
|
||||
|
||||
[I2P에 대한 자세한 내용은 프로젝트 웹 사이트를 방문하십시오.](https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [리시드에 대해 자세히 알아보기](https://geti2p.net/en/docs/reseed)
|
||||
- [리시드 실행 방법 알아보기](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [리시드 서버 코드를 읽고 더 많은 리시드 옵션에 대해 알아보세요](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### 연결 문제가 있습니까? 다음은 reseed 번들에 대한 일회성 링크입니다.
|
18
content/lang/pr/homepage.md
Normal file
18
content/lang/pr/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Este é um servidor I2P Reseed
|
||||
==============================
|
||||
|
||||
I2P é uma rede ponto a ponto que usa “Roteamento de alho” para manter a privacidade.
|
||||
Nós Reseed ajudam você a se conectar ao I2P pela primeira vez, e mesmo que
|
||||
você só deve ter que usá-los de vez em quando, eles são muito importantes
|
||||
Serviços.
|
||||
|
||||
[Para saber mais sobre I2P, visite o site do projeto] (https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[! [Help reseed] (images / reseed.png)] (https://geti2p.net)
|
||||
|
||||
- [Saiba mais sobre reseeds] (https://geti2p.net/en/docs/reseed)
|
||||
- [Saiba como executar uma nova propagação] (https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Leia o código do servidor de nova propagação e aprenda sobre mais opções de nova propagação] (https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Tendo problemas de conexão? Aqui está um link único para um pacote reenviado para você.
|
18
content/lang/ru/homepage.md
Normal file
18
content/lang/ru/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Это сервер I2P Reseed
|
||||
============================
|
||||
|
||||
I2P - это одноранговая сеть, которая использует «Garlic Routing» для обеспечения конфиденциальности.
|
||||
Узлы с повторным заполнением помогут вам впервые подключиться к I2P, и даже если
|
||||
вы должны использовать их только время от времени, они очень важны
|
||||
Сервисы.
|
||||
|
||||
[Чтобы узнать больше об I2P, посетите сайт проекта] (https://geti2p.net)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
[! [Повторное заполнение справки] (images / Reseed.png)] (https://geti2p.net)
|
||||
|
||||
- [Подробнее о Reseeds] (https://geti2p.net/en/docs/reseed)
|
||||
- [Узнайте, как запустить повторное заполнение] (https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [Прочтите код сервера повторного заполнения и узнайте о дополнительных параметрах повторного заполнения] (https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### Возникли проблемы с подключением? Вот вам одноразовая ссылка на набор повторных рассылок.
|
18
content/lang/zh/homepage.md
Normal file
18
content/lang/zh/homepage.md
Normal file
@@ -0,0 +1,18 @@
|
||||
这是一个 I2P Reseed 服务器
|
||||
============================
|
||||
|
||||
I2P 是一种点对点网络,它使用“大蒜路由”来维护隐私。
|
||||
Reseed 节点可帮助您首次连接到 I2P,即使
|
||||
你应该只需要偶尔使用它们,它们非常重要
|
||||
服务。
|
||||
|
||||
【了解更多关于I2P,请访问项目网站】(https://geti2p.net)
|
||||
-----------------------------------------------------------------
|
||||
|
||||
[](https://geti2p.net)
|
||||
|
||||
- [了解更多关于 reseeds](https://geti2p.net/en/docs/reseed)
|
||||
- [了解如何进行重新播种](https://geti2p.net/en/get-involved/guides/reseed)
|
||||
- [阅读 reseed 服务器代码并了解更多 reseed 选项](https://i2pgit.org/idk/reseed-tools)
|
||||
|
||||
### 有连接问题? 这是为您提供的重新种子包的一次性链接。
|
0
content/script.js
Normal file
0
content/script.js
Normal file
77
content/style.css
Normal file
77
content/style.css
Normal file
@@ -0,0 +1,77 @@
|
||||
body {
|
||||
font-family: "Roboto", monospace;
|
||||
text-align: justify;
|
||||
background-color: #D9D9D9;
|
||||
}
|
||||
h1 {
|
||||
width: 55%;
|
||||
margin-left: 45%;
|
||||
margin-top: 5%;
|
||||
}
|
||||
h2 {
|
||||
width: 55%;
|
||||
margin-left: 45%;
|
||||
}
|
||||
#homepage > h2:nth-child(3) > a:nth-child(1) {
|
||||
text-decoration: none;
|
||||
}
|
||||
h3 {
|
||||
width: 55%;
|
||||
margin-left: 45%;
|
||||
}
|
||||
ul {
|
||||
width: 55%;
|
||||
display: block;
|
||||
margin-left: 40%;
|
||||
}
|
||||
li {
|
||||
margin-top: 1%;
|
||||
margin-left: 20%;
|
||||
}
|
||||
p {
|
||||
max-width: 55%;
|
||||
font-size: 1.2em;
|
||||
margin-right: 2%;
|
||||
}
|
||||
#homepage > p:nth-child(2){
|
||||
margin-left: 45%;
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
margin-top: 3%;
|
||||
top: 5%;
|
||||
left: 5%;
|
||||
width: 35%;
|
||||
display: inline;
|
||||
margin-bottom: 5%;
|
||||
padding-bottom: 5%;
|
||||
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
margin-top: 3%;
|
||||
padding: 2%;
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
margin-left: -3%;
|
||||
border-radius: 20%;
|
||||
border-style: groove;
|
||||
}
|
||||
|
||||
.link-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.link-button:active {
|
||||
color:red;
|
||||
}
|
||||
|
||||
figure > img {
|
||||
max-width: 35%;
|
||||
display: inline;
|
||||
}
|
1
description-pak
Normal file
1
description-pak
Normal file
@@ -0,0 +1 @@
|
||||
Reseed tools is a self-contained, easy-to-configure I2P reseed service which can be run on any OS.
|
7
entrypoint.sh
Executable file
7
entrypoint.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#! /usr/bin/env sh
|
||||
|
||||
cd /var/lib/i2p/i2p-config/reseed
|
||||
|
||||
cp -r /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/content ./content
|
||||
|
||||
/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/reseed-tools reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb $@
|
2
etc/default/reseed
Normal file
2
etc/default/reseed
Normal file
@@ -0,0 +1,2 @@
|
||||
#Edit the contact/signing email used by your reseed server here
|
||||
export RESEED_EMAIL=""
|
69
etc/init.d/reseed
Normal file
69
etc/init.d/reseed
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: samcatd
|
||||
# Required-Start: $local_fs $network $named $time $syslog
|
||||
# Required-Stop: $local_fs $network $named $time $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: <DESCRIPTION>
|
||||
### END INIT INFO
|
||||
|
||||
SCRIPT='/usr/bin/reseed-tools'
|
||||
RUNAS=i2psvc
|
||||
NETDBDIR=/var/lib/i2p/i2p-config/netDb
|
||||
RUNDIR=/var/lib/i2p/i2p-config/reseed
|
||||
MORE_OPTIONS=""
|
||||
if [ -f /etc/default/reseed ]; then
|
||||
. /etc/default/reseed
|
||||
fi
|
||||
RUNOPTS=" reseed --yes=true --netdb=$NETDBDIR $MORE_OPTIONS "
|
||||
|
||||
start() {
|
||||
start-stop-daemon --background --user $RUNAS --chuid $RUNAS --exec $SCRIPT --chdir $RUNDIR --make-pidfile --pidfile $RUNDIR/reseed.pid --start -- $RUNOPTS
|
||||
}
|
||||
|
||||
stop() {
|
||||
start-stop-daemon --background --user $RUNAS --exec $SCRIPT --chdir $RUNDIR --remove-pidfile --pidfile $RUNDIR/reseed.pid --stop
|
||||
}
|
||||
|
||||
status() {
|
||||
start-stop-daemon --background --user $RUNAS --exec $SCRIPT --chdir $RUNDIR --pidfile $RUNDIR/reseed.pid --status
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
|
||||
local SURE
|
||||
read SURE
|
||||
if [ "$SURE" = "yes" ]; then
|
||||
stop
|
||||
rm -f "$PIDFILE"
|
||||
echo "Notice: log file is not be removed: '$LOGFILE'" >&2
|
||||
update-rc.d -f reseed remove
|
||||
rm -fv "$0"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
uninstall)
|
||||
uninstall
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|uninstall}"
|
||||
esac
|
5
etc/systemd/system/reseed.d/reseed.conf
Normal file
5
etc/systemd/system/reseed.d/reseed.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
# Use this file to configure the contact/signer email used for the reseed service.
|
||||
# without it the reseed will fail to start.
|
||||
|
||||
[Service]
|
||||
Environment="RESEED_EMAIL="
|
17
etc/systemd/system/reseed.d/reseed.service
Normal file
17
etc/systemd/system/reseed.d/reseed.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=I2P reseed service
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
Requires=i2p.service
|
||||
|
||||
[Service]
|
||||
User=i2psvc
|
||||
RuntimeDirectory=/var/lib/i2p/i2p-config/reseed
|
||||
WorkingDirectory=/var/lib/i2p/i2p-config/reseed
|
||||
ExecStart=/usr/bin/reseed-tools reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
RuntimeMaxSec=43200
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
43
go.mod
43
go.mod
@@ -1,23 +1,34 @@
|
||||
module github.com/eyedeekay/i2p-tools-1
|
||||
module i2pgit.org/idk/reseed-tools
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce
|
||||
github.com/MDrollette/i2p-tools v0.0.0
|
||||
github.com/codegangsta/cli v1.22.1
|
||||
github.com/cretz/bine v0.1.0
|
||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/hashicorp/golang-lru v0.5.3 // indirect
|
||||
github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da
|
||||
github.com/stretchr/testify v1.4.0 // indirect
|
||||
github.com/throttled/throttled v2.2.4+incompatible
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf // indirect
|
||||
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 // indirect
|
||||
gopkg.in/throttled/throttled.v2 v2.2.4 // indirect
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/eyedeekay/checki2cp v0.0.21
|
||||
github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc
|
||||
github.com/eyedeekay/sam3 v0.32.32
|
||||
github.com/go-acme/lego/v4 v4.3.1
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/hjson/hjson-go v3.1.0+incompatible
|
||||
github.com/justinas/alice v1.2.0
|
||||
github.com/libp2p/go-libp2p v0.13.0
|
||||
github.com/libp2p/go-libp2p-core v0.8.0
|
||||
github.com/libp2p/go-libp2p-gostream v0.3.1
|
||||
github.com/libp2p/go-libp2p-http v0.2.0
|
||||
github.com/mitchellh/mapstructure v1.4.1
|
||||
github.com/throttled/throttled/v2 v2.7.1
|
||||
github.com/urfave/cli v1.22.5
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.4.3
|
||||
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19
|
||||
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b
|
||||
)
|
||||
|
||||
replace github.com/MDrollette/i2p-tools v0.0.0 => ./
|
||||
replace github.com/libp2p/go-libp2p => github.com/libp2p/go-libp2p v0.13.0
|
||||
|
||||
replace github.com/codegangsta/cli v1.22.1 => github.com/urfave/cli v1.22.1
|
||||
replace github.com/libp2p/go-libp2p-core => github.com/libp2p/go-libp2p-core v0.8.0
|
||||
|
||||
replace github.com/libp2p/go-libp2p-gostream => github.com/libp2p/go-libp2p-gostream v0.3.1
|
||||
|
||||
replace github.com/libp2p/go-libp2p-http => github.com/libp2p/go-libp2p-http v0.2.0
|
||||
|
||||
replace github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc => ./go-i2pd
|
||||
|
@@ -3,6 +3,7 @@
|
||||
* incorporate libp2p(ipfs) listener from RTradeLtd/i2p-tools-1 master
|
||||
* in-network(I2P) reseeds in case there's a point to that.
|
||||
* self-supervising reseed service, if it crashes it will restart itself
|
||||
* add an initscript
|
||||
|
||||
2019-06-27
|
||||
* automatically configuring Tor Onionv3 Server
|
||||
@@ -40,4 +41,4 @@
|
||||
* numRi per su3 file: 75 --> 77
|
||||
|
||||
2016-01
|
||||
* fork from https://github.com/MDrollette/i2p-tools
|
||||
* fork from https://i2pgit.org/idk/reseed-tools
|
||||
|
424
index.html
Normal file
424
index.html
Normal file
@@ -0,0 +1,424 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
I2P Reseed Tools
|
||||
</title>
|
||||
<meta name="author" content="eyedeekay" />
|
||||
<meta name="description" content="reseed-tools" />
|
||||
<meta name="keywords" content="yggdrasil-direct" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<a href="#shownav">
|
||||
Show navigation
|
||||
</a>
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="CHANGELOG.html">
|
||||
CHANGELOG
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="DOCKER.html">
|
||||
DOCKER
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EXAMPLES.html">
|
||||
EXAMPLES
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
<a href="#hidenav">
|
||||
Hide Navigation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1>
|
||||
<a href="/">
|
||||
I2P Reseed Tools
|
||||
</a>
|
||||
</h1>
|
||||
<p>
|
||||
<img src="content/images/reseed.png" alt="Reseed Tools Poster"/>
|
||||
</p>
|
||||
<p>
|
||||
This tool provides a secure and efficient reseed server for the I2P network.
|
||||
There are several utility commands to create, sign, and validate SU3 files.
|
||||
Please note that this requires at least Go version 1.13, and uses Go Modules.
|
||||
</p>
|
||||
<p>
|
||||
Standard reseeds are distributed with the I2P packages. To get your reseed
|
||||
included, apply on
|
||||
<a href="http://zzz.i2p" rel="nofollow">
|
||||
zzz.i2p
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<h2>
|
||||
Dependencies
|
||||
</h2>
|
||||
<p>
|
||||
<code>
|
||||
go
|
||||
</code>
|
||||
,
|
||||
<code>
|
||||
git
|
||||
</code>
|
||||
, and optionally
|
||||
<code>
|
||||
make
|
||||
</code>
|
||||
are required to build the project.
|
||||
Precompiled binaries for most platforms are available at my github mirror
|
||||
<a href="https://github.com/eyedeekay/i2p-tools-1" rel="nofollow">
|
||||
https://github.com/eyedeekay/i2p-tools-1
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
In order to install the build-dependencies on Ubuntu or Debian, you may use:
|
||||
</p>
|
||||
<pre><code>sudo apt-get install golang-go git make
|
||||
</code></pre>
|
||||
<h2>
|
||||
Installation
|
||||
</h2>
|
||||
<p>
|
||||
Reseed-tools can be run as a user, as a freestanding service, or be installed
|
||||
as an I2P Plugin. It will attempt to configure itself automatically. You should
|
||||
make sure to set the
|
||||
<code>
|
||||
--signer
|
||||
</code>
|
||||
flag or the
|
||||
<code>
|
||||
RESEED_EMAIL
|
||||
</code>
|
||||
environment variable
|
||||
to configure your signing keys/contact info.
|
||||
</p>
|
||||
<h4>
|
||||
Plugin install URL’s
|
||||
</h4>
|
||||
<p>
|
||||
Plugin releases are available inside of i2p at
|
||||
<a href="http://idk.i2p/reseed-tools/" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/
|
||||
</a>
|
||||
and via the github mirror at
|
||||
<a href="https://github.com/eyedeekay/reseed-tools/releases" rel="nofollow">
|
||||
https://github.com/eyedeekay/reseed-tools/releases
|
||||
</a>
|
||||
.
|
||||
These can be installed by adding them on the
|
||||
<a href="http://127.0.0.1:7657/configplugins" rel="nofollow">
|
||||
http://127.0.0.1:7657/configplugins
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
After installing the plugin, you should immediately edit the
|
||||
<code>
|
||||
$PLUGIN/signer
|
||||
</code>
|
||||
file in order to set your
|
||||
<code>
|
||||
--signer
|
||||
</code>
|
||||
email, which is used to name your keys.
|
||||
You can find the
|
||||
<code>
|
||||
$PLUGIN
|
||||
</code>
|
||||
directory in your I2P config directory, which is
|
||||
usually
|
||||
<code>
|
||||
$HOME/.i2p
|
||||
</code>
|
||||
on Unixes.
|
||||
</p>
|
||||
<p>
|
||||
This will allow the developers to contact you if your reseed has issues
|
||||
and will authenticate your reseed to the I2P routers that use it.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
darwin/amd64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-darwin-amd64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-darwin-amd64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
darwin/arm64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-darwin-arm64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-darwin-arm64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
linux/386:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-linux-386.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-linux-386.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
linux/amd64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-linux-amd64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-linux-amd64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
linux/arm:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-linux-arm.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-linux-arm.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
linux/arm64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-linux-arm64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-linux-arm64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
openbsd/amd64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-openbsd-amd64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-openbsd-amd64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
freebsd/386:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-freebsd-386.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-freebsd-386.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
freebsd/amd64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-freebsd-amd64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-freebsd-amd64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
windows/amd64:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-windows-amd64.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-windows-amd64.su3
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
windows/386:
|
||||
<a href="http://idk.i2p/reseed-tools/reseed-tools-windows-386.su3" rel="nofollow">
|
||||
http://idk.i2p/reseed-tools/reseed-tools-windows-386.su3
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Installation(From Source)
|
||||
</h3>
|
||||
<pre><code>git clone https://i2pgit.org/idk/reseed-tools
|
||||
cd reseed-tools
|
||||
make build
|
||||
# Optionally, if you want to install to /usr/bin/reseed-tools
|
||||
sudo make install
|
||||
</code></pre>
|
||||
<h2>
|
||||
Usage
|
||||
</h2>
|
||||
<h4>
|
||||
Debian/Ubuntu note:
|
||||
</h4>
|
||||
<p>
|
||||
Debian users who are running I2P as a system service must also run the
|
||||
<code>
|
||||
reseed-tools
|
||||
</code>
|
||||
as the same user. This is so that the reseed-tools can access
|
||||
the I2P service’s netDb directory. On Debian and Ubuntu, that user is
|
||||
<code>
|
||||
i2psvc
|
||||
</code>
|
||||
and the netDb directory is:
|
||||
<code>
|
||||
/var/lib/i2p/i2p-config/netDb
|
||||
</code>
|
||||
.
|
||||
</p>
|
||||
<h5>
|
||||
Service Integration
|
||||
</h5>
|
||||
<p>
|
||||
Support for running as a system service as part of the reseed package
|
||||
is new. PR’s that improve integration are welcome.
|
||||
</p>
|
||||
<h6>
|
||||
Systemd Service
|
||||
</h6>
|
||||
<p>
|
||||
A systemd service is provided which should work with the I2P Debian package
|
||||
when reseed-tools is installed in
|
||||
<code>
|
||||
/usr/bin/reseed-tools
|
||||
</code>
|
||||
. If you install with
|
||||
<code>
|
||||
make install
|
||||
</code>
|
||||
this service is also installed. This service will cause the
|
||||
bundles to regenerate every 12 hours.
|
||||
</p>
|
||||
<p>
|
||||
The contact email for your reseed should be added in:
|
||||
<code>
|
||||
/etc/systemd/system/reseed.d/reseed.conf
|
||||
</code>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
Self-signed certificates will be auto-generated for these services. To change
|
||||
this you should edit the
|
||||
<code>
|
||||
/etc/systemd/system/reseed.d/reseed.service
|
||||
</code>
|
||||
.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
To enable starting the reseed service automatically with the system:
|
||||
<code>
|
||||
sudo systemctl enable reseed.service
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
To run the service manually:
|
||||
<code>
|
||||
sudo sysctl start reseed.service
|
||||
</code>
|
||||
<br/>
|
||||
</li>
|
||||
<li>
|
||||
To reload the systemd services:
|
||||
<code>
|
||||
sudo systemctl daemon-reload
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
To view the status/logs:
|
||||
<code>
|
||||
sudo journalctl -u reseed.service
|
||||
</code>
|
||||
</li>
|
||||
</ul>
|
||||
<h6>
|
||||
SysV Service
|
||||
</h6>
|
||||
<p>
|
||||
An initscript is also provided. The initscript, unlike the systemd service,
|
||||
cannot schedule itself to restart. You should restart the service roughly once
|
||||
a day to ensure that the information does not expire.
|
||||
</p>
|
||||
<p>
|
||||
The contact email for your reseed should be added in:
|
||||
<code>
|
||||
/etc/init.d/reseed
|
||||
</code>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
Self-signed certificates will be auto-generated for these services. To change
|
||||
this you should edit the
|
||||
<code>
|
||||
/etc/init.d/reseed
|
||||
</code>
|
||||
.
|
||||
</p>
|
||||
<h2>
|
||||
Example Commands:
|
||||
</h2>
|
||||
<h3>
|
||||
Without a webserver, standalone with TLS support
|
||||
</h3>
|
||||
<p>
|
||||
If this is your first time running a reseed server (ie. you don’t have any existing keys),
|
||||
you can simply run the command and follow the prompts to create the appropriate keys, crl and certificates.
|
||||
Afterwards an HTTPS reseed server will start on the default port and generate 6 files in your current directory
|
||||
(a TLS key, certificate and crl, and a su3-file signing key, certificate and crl).
|
||||
</p>
|
||||
<pre><code>reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
|
||||
</code></pre>
|
||||
<h3>
|
||||
Locally behind a webserver (reverse proxy setup), preferred:
|
||||
</h3>
|
||||
<p>
|
||||
If you are using a reverse proxy server it may provide the TLS certificate instead.
|
||||
</p>
|
||||
<pre><code>reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
|
||||
</code></pre>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>
|
||||
Usage
|
||||
</strong>
|
||||
<a href="EXAMPLES.md" rel="nofollow">
|
||||
More examples can be found here.
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong>
|
||||
Docker
|
||||
</strong>
|
||||
<a href="DOCKER.md" rel="nofollow">
|
||||
Docker examples can be found here
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<a href="#show">
|
||||
Show license
|
||||
</a>
|
||||
<div id="show">
|
||||
<div id="hide">
|
||||
<pre><code>Copyright (c) 2014 Matt Drollette
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</code></pre>
|
||||
<a href="#hide">
|
||||
Hide license
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<iframe src="https://snowflake.torproject.org/embed.html" width="320" height="240" frameborder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://geti2p.net/">
|
||||
I2P
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
8
main.go
8
main.go
@@ -4,8 +4,8 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/MDrollette/i2p-tools/cmd"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/urfave/cli"
|
||||
"i2pgit.org/idk/reseed-tools/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -18,8 +18,8 @@ func main() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU() / 2)
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "i2p-tools-1"
|
||||
app.Version = "0.1.7"
|
||||
app.Name = "reseed-tools"
|
||||
app.Version = "0.2.9"
|
||||
app.Usage = "I2P tools and reseed server"
|
||||
app.Author = "eyedeekay"
|
||||
app.Email = "hankhill19580@gmail.com"
|
||||
|
35
postinstall-pak
Executable file
35
postinstall-pak
Executable file
@@ -0,0 +1,35 @@
|
||||
#! /usr/bin/env sh
|
||||
RESEED_MESSAGE="Reseed Tools requires you to set an email for contact purposes.
|
||||
This is in case your reseed goes down.
|
||||
Please enter your email below."
|
||||
|
||||
RESEED_CONF="# Use this file to configure the contact/signer email used for the reseed service.
|
||||
# without it the reseed will fail to start.
|
||||
|
||||
[Service]
|
||||
Environment=\"RESEED_EMAIL="
|
||||
|
||||
RESEED_DEFAULT="#Edit the contact/signing email used by your reseed server here
|
||||
export RESEED_EMAIL=\""
|
||||
|
||||
mkdir -p /etc/systemd/system/reseed.d/
|
||||
|
||||
if [ -f /usr/bin/zenity ]; then
|
||||
RESEED_EMAIL=$(zenity --entry --title "Reseed Configuration" --text "$RESEED_MESSAGE" 10 30 3>&1 1>&2 2>&3)
|
||||
echo "$RESEED_DEFAULT$RESEED_EMAIL\"" >> /etc/default/reseed
|
||||
echo "$RESEED_CONF$RESEED_EMAIL\"" >> /etc/systemd/system/reseed.d/reseed.conf
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -t 1 ] ; then
|
||||
echo "proceeding with terminal";
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -f /usr/bin/whiptail ]; then
|
||||
RESEED_EMAIL=$(whiptail --inputbox "$RESEED_MESSAGE" 10 30 3>&1 1>&2 2>&3)
|
||||
echo "$RESEED_DEFAULT$RESEED_EMAIL\"" >> /etc/default/reseed
|
||||
echo "$RESEED_CONF$RESEED_EMAIL\"" >> /etc/systemd/system/reseed.d/reseed.conf
|
||||
exit 0
|
||||
fi
|
163
reseed/homepage.go
Normal file
163
reseed/homepage.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package reseed
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitlab.com/golang-commonmark/markdown"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var SupportedLanguages = []language.Tag{
|
||||
language.English,
|
||||
language.Russian,
|
||||
language.SimplifiedChinese,
|
||||
language.Arabic,
|
||||
language.Portuguese,
|
||||
language.German,
|
||||
language.French,
|
||||
language.Spanish,
|
||||
language.Indonesian,
|
||||
language.Hindi,
|
||||
language.Japanese,
|
||||
language.Korean,
|
||||
language.Bengali,
|
||||
}
|
||||
var CachedLanguagePages = map[string]string{}
|
||||
var CachedDataPages = map[string][]byte{}
|
||||
|
||||
var BaseContentPath, ContentPathError = ContentPath()
|
||||
|
||||
var matcher = language.NewMatcher(SupportedLanguages)
|
||||
|
||||
var header = []byte(`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>This is an I2P Reseed Server</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="script.js"></script>
|
||||
</head>
|
||||
<body>`)
|
||||
var footer = []byte(` </body>
|
||||
</html>`)
|
||||
|
||||
var md = markdown.New(markdown.XHTMLOutput(true), markdown.HTML(true))
|
||||
|
||||
func ContentPath() (string, error) {
|
||||
exPath, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
//exPath := filepath.Dir(ex)
|
||||
if _, err := os.Stat(filepath.Join(exPath, "content")); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(exPath, "content"), nil
|
||||
}
|
||||
|
||||
func (srv *Server) HandleARealBrowser(w http.ResponseWriter, r *http.Request) {
|
||||
if ContentPathError != nil {
|
||||
http.Error(w, "403 Forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
lang, _ := r.Cookie("lang")
|
||||
accept := r.Header.Get("Accept-Language")
|
||||
log.Printf("lang: '%s', accept: '%s'\n", lang, accept)
|
||||
for name, values := range r.Header {
|
||||
// Loop over all values for the name.
|
||||
for _, value := range values {
|
||||
log.Printf("name: '%s', value: '%s'\n", name, value)
|
||||
}
|
||||
}
|
||||
tag, _ := language.MatchStrings(matcher, lang.String(), accept)
|
||||
log.Printf("tag: '%s'\n", tag)
|
||||
base, _ := tag.Base()
|
||||
log.Printf("base: '%s'\n", base)
|
||||
|
||||
switch r.URL.Path {
|
||||
case "/style.css":
|
||||
w.Header().Set("Content-Type", "text/css")
|
||||
HandleAFile(w, "", "style.css")
|
||||
case "/script.js":
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
HandleAFile(w, "", "script.js")
|
||||
default:
|
||||
image := strings.Replace(r.URL.Path, "/", "", -1)
|
||||
if strings.HasPrefix(image, "images") {
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
HandleAFile(w, "images", strings.TrimPrefix(strings.TrimPrefix(r.URL.Path, "/"), "images"))
|
||||
} else if strings.HasPrefix(image, "ping") {
|
||||
PingEverybody()
|
||||
http.Redirect(w, r, "/readout", http.StatusFound)
|
||||
} else if strings.HasPrefix(image, "readout") {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write([]byte(header))
|
||||
ReadOut(w)
|
||||
w.Write([]byte(footer))
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write([]byte(header))
|
||||
HandleALocalizedFile(w, base.String())
|
||||
w.Write([]byte(`<ul><li><form method="post" action="/i2pseeds" class="inline">
|
||||
<input type="hidden" name="onetime" value="` + srv.Acceptable() + `">
|
||||
<button type="submit" name="submit_param" value="submit_value" class="link-button">
|
||||
Reseed
|
||||
</button>
|
||||
</form></li></ul>`))
|
||||
ReadOut(w)
|
||||
w.Write([]byte(footer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func HandleAFile(w http.ResponseWriter, dirPath, file string) {
|
||||
file = filepath.Join(dirPath, file)
|
||||
if _, prs := CachedDataPages[file]; !prs {
|
||||
path := filepath.Join(BaseContentPath, file)
|
||||
f, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
|
||||
return
|
||||
}
|
||||
CachedDataPages[file] = f
|
||||
w.Write([]byte(CachedDataPages[file]))
|
||||
} else {
|
||||
w.Write(CachedDataPages[file])
|
||||
}
|
||||
}
|
||||
|
||||
func HandleALocalizedFile(w http.ResponseWriter, dirPath string) {
|
||||
if _, prs := CachedLanguagePages[dirPath]; !prs {
|
||||
dir := filepath.Join(BaseContentPath, "lang", dirPath)
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
|
||||
}
|
||||
var f []byte
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(file.Name(), ".md") {
|
||||
return
|
||||
}
|
||||
trimmedName := strings.TrimSuffix(file.Name(), ".md")
|
||||
path := filepath.Join(dir, file.Name())
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
|
||||
return
|
||||
}
|
||||
f = append(f, []byte(`<div id="`+trimmedName+`">`)...)
|
||||
f = append(f, []byte(md.RenderToString(b))...)
|
||||
f = append(f, []byte(`</div>`)...)
|
||||
|
||||
}
|
||||
CachedLanguagePages[dirPath] = string(f)
|
||||
w.Write([]byte(CachedLanguagePages[dirPath]))
|
||||
} else {
|
||||
w.Write([]byte(CachedLanguagePages[dirPath]))
|
||||
}
|
||||
}
|
123
reseed/ping.go
Normal file
123
reseed/ping.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package reseed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Ping requests an `.su3` from another reseed server and return true if
|
||||
// the reseed server is alive If the reseed server is not alive, returns
|
||||
// false and the status of the request as an error
|
||||
func Ping(url string) (bool, error) {
|
||||
if strings.HasSuffix(url, "i2pseeds.su3") {
|
||||
url = url + "i2pseeds.su3"
|
||||
}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
req.Header.Set("User-Agent", i2pUserAgent)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return false, fmt.Errorf("%s", resp.Status)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func PingWriteContent(url string) error {
|
||||
date := time.Now().Format("2006-01-02")
|
||||
path := strings.Replace(url, "http://", "", 1)
|
||||
path = strings.Replace(path, "https://", "", 1)
|
||||
path = strings.Replace(path, "/", "", -1)
|
||||
path = filepath.Join(BaseContentPath, path+"-"+date+".ping")
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
result, err := Ping(url)
|
||||
if result {
|
||||
log.Printf("Ping: %s OK", url)
|
||||
err := ioutil.WriteFile(path, []byte("Alive: Status OK"), 0644)
|
||||
return err
|
||||
} else {
|
||||
log.Printf("Ping: %s %s", url, err)
|
||||
err := ioutil.WriteFile(path, []byte("Dead: "+err.Error()), 0644)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//TODO: make this a configuration option
|
||||
var AllReseeds = []string{
|
||||
"https://banana.incognet.io/",
|
||||
"https://i2p.novg.net/",
|
||||
"https://i2pseed.creativecowpat.net:8443/",
|
||||
"https://reseed.diva.exchange/",
|
||||
"https://reseed.i2pgit.org/",
|
||||
"https://reseed.memcpy.io/",
|
||||
"https://reseed.onion.im/",
|
||||
"https://reseed2.i2p.net/",
|
||||
}
|
||||
|
||||
func PingEverybody() []string {
|
||||
var nonerrs []string
|
||||
for _, url := range AllReseeds {
|
||||
err := PingWriteContent(url)
|
||||
if err == nil {
|
||||
nonerrs = append(nonerrs, url)
|
||||
} else {
|
||||
nonerrs = append(nonerrs, err.Error()+"-"+url)
|
||||
}
|
||||
}
|
||||
return nonerrs
|
||||
}
|
||||
|
||||
// Get a list of all files ending in ping in the BaseContentPath
|
||||
func GetPingFiles() ([]string, error) {
|
||||
var files []string
|
||||
date := time.Now().Format("2006-01-02")
|
||||
err := filepath.Walk(BaseContentPath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(path, ".ping") && strings.Contains(path, date) {
|
||||
files = append(files, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if len(files) == 0 {
|
||||
return nil, fmt.Errorf("No ping files found")
|
||||
}
|
||||
return files, err
|
||||
}
|
||||
|
||||
func ReadOut(w http.ResponseWriter) {
|
||||
pinglist, err := GetPingFiles()
|
||||
if err == nil {
|
||||
fmt.Fprintf(w, "<h3>Reseed Server Statuses</h3>")
|
||||
fmt.Fprintf(w, "<div><p>This feature is experimental and may not always provide accurate results.</p></div>")
|
||||
fmt.Fprintf(w, "</div><p><ul>")
|
||||
for _, file := range pinglist {
|
||||
ping, err := ioutil.ReadFile(file)
|
||||
host := strings.Replace(file, ".ping", "", 1)
|
||||
host = filepath.Base(host)
|
||||
if err == nil {
|
||||
fmt.Fprintf(w, "<li><strong>%s</strong> - %s</li>\n", host, ping)
|
||||
} else {
|
||||
fmt.Fprintf(w, "<li><strong>%s</strong> - No ping file found</li>\n", host)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "</ul></p></div>")
|
||||
} else {
|
||||
fmt.Fprintf(w, "<h4>No ping files found, check back later for reseed stats</h4>")
|
||||
}
|
||||
}
|
212
reseed/server.go
212
reseed/server.go
@@ -3,11 +3,17 @@ package reseed
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
mrand "math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -16,12 +22,20 @@ import (
|
||||
"github.com/eyedeekay/sam3"
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/hjson/hjson-go"
|
||||
"github.com/justinas/alice"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
gostream "github.com/libp2p/go-libp2p-gostream"
|
||||
p2phttp "github.com/libp2p/go-libp2p-http"
|
||||
"github.com/throttled/throttled"
|
||||
"github.com/throttled/throttled/store"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
throttled "github.com/throttled/throttled/v2"
|
||||
"github.com/throttled/throttled/v2/store"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -34,9 +48,19 @@ type Server struct {
|
||||
I2PSession *sam3.StreamSession
|
||||
I2PListener *sam3.StreamListener
|
||||
I2PKeys i2pkeys.I2PKeys
|
||||
Reseeder Reseeder
|
||||
Reseeder *ReseederImpl
|
||||
Blacklist *Blacklist
|
||||
OnionListener *tor.OnionService
|
||||
YggdrasilConf string
|
||||
yggdrasilNode *node
|
||||
acceptables map[string]time.Time
|
||||
}
|
||||
type node struct {
|
||||
core *core.Core
|
||||
config *config.NodeConfig
|
||||
multicast *multicast.Multicast
|
||||
//tuntap *tuntap.TunAdapter
|
||||
//admin *admin.AdminSocket
|
||||
}
|
||||
|
||||
func NewServer(prefix string, trustProxy bool) *Server {
|
||||
@@ -65,6 +89,7 @@ func NewServer(prefix string, trustProxy bool) *Server {
|
||||
server := Server{Server: h, Reseeder: nil}
|
||||
|
||||
th := throttled.RateLimit(throttled.PerHour(4), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000))
|
||||
thw := throttled.RateLimit(throttled.PerHour(30), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000))
|
||||
|
||||
middlewareChain := alice.New()
|
||||
if trustProxy {
|
||||
@@ -79,13 +104,85 @@ func NewServer(prefix string, trustProxy bool) *Server {
|
||||
})
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware).Then(errorHandler))
|
||||
mux.Handle("/", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, thw.Throttle, server.browsingMiddleware).Then(errorHandler))
|
||||
mux.Handle(prefix+"/i2pseeds.su3", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, verifyMiddleware, th.Throttle).Then(http.HandlerFunc(server.reseedHandler)))
|
||||
server.Handler = mux
|
||||
|
||||
return &server
|
||||
}
|
||||
|
||||
// See use of crypto/rand on:
|
||||
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
|
||||
const (
|
||||
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52 possibilities
|
||||
letterIdxBits = 6 // 6 bits to represent 64 possibilities / indexes
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
)
|
||||
|
||||
func SecureRandomAlphaString() string {
|
||||
length := 16
|
||||
result := make([]byte, length)
|
||||
bufferSize := int(float64(length) * 1.3)
|
||||
for i, j, randomBytes := 0, 0, []byte{}; i < length; j++ {
|
||||
if j%bufferSize == 0 {
|
||||
randomBytes = SecureRandomBytes(bufferSize)
|
||||
}
|
||||
if idx := int(randomBytes[j%length] & letterIdxMask); idx < len(letterBytes) {
|
||||
result[i] = letterBytes[idx]
|
||||
i++
|
||||
}
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
// SecureRandomBytes returns the requested number of bytes using crypto/rand
|
||||
func SecureRandomBytes(length int) []byte {
|
||||
var randomBytes = make([]byte, length)
|
||||
_, err := rand.Read(randomBytes)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to generate random bytes")
|
||||
}
|
||||
return randomBytes
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func (srv *Server) Acceptable() string {
|
||||
if srv.acceptables == nil {
|
||||
srv.acceptables = make(map[string]time.Time)
|
||||
}
|
||||
if len(srv.acceptables) > 50 {
|
||||
for val := range srv.acceptables {
|
||||
srv.CheckAcceptable(val)
|
||||
}
|
||||
for val := range srv.acceptables {
|
||||
if len(srv.acceptables) < 50 {
|
||||
break
|
||||
}
|
||||
delete(srv.acceptables, val)
|
||||
}
|
||||
}
|
||||
acceptme := SecureRandomAlphaString()
|
||||
srv.acceptables[acceptme] = time.Now()
|
||||
return acceptme
|
||||
}
|
||||
|
||||
func (srv *Server) CheckAcceptable(val string) bool {
|
||||
if srv.acceptables == nil {
|
||||
srv.acceptables = make(map[string]time.Time)
|
||||
}
|
||||
if timeout, ok := srv.acceptables[val]; ok {
|
||||
checktime := time.Now().Sub(timeout)
|
||||
if checktime > (4 * time.Minute) {
|
||||
delete(srv.acceptables, val)
|
||||
return false
|
||||
}
|
||||
delete(srv.acceptables, val)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (srv *Server) ListenAndServe() error {
|
||||
addr := srv.Addr
|
||||
if addr == "" {
|
||||
@@ -99,6 +196,97 @@ func (srv *Server) ListenAndServe() error {
|
||||
return srv.Serve(newBlacklistListener(ln, srv.Blacklist))
|
||||
}
|
||||
|
||||
func (srv *Server) YggdrasilConfigFile() (*config.NodeConfig, error) {
|
||||
var conf []byte
|
||||
var err error
|
||||
if srv.YggdrasilConf != "" {
|
||||
conf, err = ioutil.ReadFile(srv.YggdrasilConf)
|
||||
} else {
|
||||
conf, err = ioutil.ReadAll(os.Stdin)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bytes.Equal(conf[0:2], []byte{0xFF, 0xFE}) ||
|
||||
bytes.Equal(conf[0:2], []byte{0xFE, 0xFF}) {
|
||||
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||
decoder := utf.NewDecoder()
|
||||
conf, err = decoder.Bytes(conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
cfg := defaults.GenerateConfig()
|
||||
var dat map[string]interface{}
|
||||
if err := hjson.Unmarshal(conf, &dat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Sanitise the config
|
||||
confJson, err := json.Marshal(dat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(confJson, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Overlay our newly mapped configuration onto the autoconf node config that
|
||||
// we generated above.
|
||||
if err = mapstructure.Decode(dat, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (srv *Server) ListenAndServeYggdrasil() error {
|
||||
cfg, err := srv.YggdrasilConfigFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.yggdrasilNode.core = &core.Core{}
|
||||
if err = srv.yggdrasilNode.core.Start(cfg, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var interf net.Interface
|
||||
for _, iface := range interfaces {
|
||||
if iface.Flags&net.FlagUp == 0 {
|
||||
continue
|
||||
}
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
if addrs, err := iface.MulticastAddrs(); addrs == nil || err != nil {
|
||||
continue
|
||||
}
|
||||
interf = iface
|
||||
}
|
||||
addrs, err := interf.MulticastAddrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr := addrs[0].(*net.IPAddr)
|
||||
srv.yggdrasilNode.multicast = &multicast.Multicast{}
|
||||
srv.yggdrasilNode.multicast.Init(srv.yggdrasilNode.core, srv.yggdrasilNode.config, nil, nil)
|
||||
// get a random port above say, 40000
|
||||
port := 40000 + int(mrand.Int31n(10000))
|
||||
url, err := url.Parse("tcp://" + addr.IP.String() + fmt.Sprintf(":%d", port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ln, err := srv.yggdrasilNode.core.Listen(url, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.Serve(newBlacklistListener(ln.Listener, srv.Blacklist))
|
||||
}
|
||||
|
||||
func (srv *Server) YggdrasilAddr() string {
|
||||
return srv.yggdrasilNode.core.Address().String()
|
||||
}
|
||||
|
||||
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
|
||||
addr := srv.Addr
|
||||
if addr == "" {
|
||||
@@ -245,7 +433,7 @@ func (srv *Server) ListenAndServeI2P(samaddr string, I2PKeys i2pkeys.I2PKeys) er
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("I2P server started on http://%v.onion\n", srv.OnionListener.ID)
|
||||
log.Printf("I2P server started on http://%v.b32.i2p\n", srv.I2PListener.Addr().(i2pkeys.I2PAddr).Base32())
|
||||
return srv.Serve(srv.I2PListener)
|
||||
}
|
||||
|
||||
@@ -291,6 +479,20 @@ func loggingMiddleware(next http.Handler) http.Handler {
|
||||
return handlers.CombinedLoggingHandler(os.Stdout, next)
|
||||
}
|
||||
|
||||
func (srv *Server) browsingMiddleware(next http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
if srv.CheckAcceptable(r.FormValue("onetime")) {
|
||||
srv.reseedHandler(w, r)
|
||||
}
|
||||
if i2pUserAgent != r.UserAgent() {
|
||||
srv.HandleARealBrowser(w, r)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func verifyMiddleware(next http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
if i2pUserAgent != r.UserAgent() {
|
||||
|
@@ -15,7 +15,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/MDrollette/i2p-tools/su3"
|
||||
"i2pgit.org/idk/reseed-tools/su3"
|
||||
)
|
||||
|
||||
type routerInfo struct {
|
||||
@@ -33,13 +33,13 @@ func (p Peer) Hash() int {
|
||||
return int(crc32.ChecksumIEEE(c))
|
||||
}
|
||||
|
||||
type Reseeder interface {
|
||||
/*type Reseeder interface {
|
||||
// get an su3 file (bytes) for a peer
|
||||
PeerSu3Bytes(peer Peer) ([]byte, error)
|
||||
}
|
||||
}*/
|
||||
|
||||
type ReseederImpl struct {
|
||||
netdb NetDbProvider
|
||||
netdb *LocalNetDbImpl
|
||||
su3s chan [][]byte
|
||||
|
||||
SigningKey *rsa.PrivateKey
|
||||
@@ -49,7 +49,7 @@ type ReseederImpl struct {
|
||||
NumSu3 int
|
||||
}
|
||||
|
||||
func NewReseeder(netdb NetDbProvider) *ReseederImpl {
|
||||
func NewReseeder(netdb *LocalNetDbImpl) *ReseederImpl {
|
||||
return &ReseederImpl{
|
||||
netdb: netdb,
|
||||
su3s: make(chan [][]byte),
|
||||
@@ -224,10 +224,10 @@ func (rs *ReseederImpl) createSu3(seeds []routerInfo) (*su3.File, error) {
|
||||
return su3File, nil
|
||||
}
|
||||
|
||||
type NetDbProvider interface {
|
||||
/*type NetDbProvider interface {
|
||||
// Get all router infos
|
||||
RouterInfos() ([]routerInfo, error)
|
||||
}
|
||||
}*/
|
||||
|
||||
type LocalNetDbImpl struct {
|
||||
Path string
|
||||
|
@@ -34,8 +34,16 @@ func SignerFilename(signer string) string {
|
||||
}
|
||||
|
||||
func NewTLSCertificate(host string, priv *ecdsa.PrivateKey) ([]byte, error) {
|
||||
return NewTLSCertificateAltNames(priv, host)
|
||||
}
|
||||
|
||||
func NewTLSCertificateAltNames(priv *ecdsa.PrivateKey, hosts ...string) ([]byte, error) {
|
||||
notBefore := time.Now()
|
||||
notAfter := notBefore.Add(5 * 365 * 24 * time.Hour)
|
||||
host := ""
|
||||
if len(hosts) > 0 {
|
||||
host = hosts[0]
|
||||
}
|
||||
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
@@ -61,9 +69,10 @@ func NewTLSCertificate(host string, priv *ecdsa.PrivateKey) ([]byte, error) {
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
DNSNames: hosts[1:],
|
||||
}
|
||||
|
||||
hosts := strings.Split(host, ",")
|
||||
hosts = strings.Split(host, ",")
|
||||
for _, h := range hosts {
|
||||
if ip := net.ParseIP(h); ip != nil {
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
|
157
style.css
Normal file
157
style.css
Normal file
@@ -0,0 +1,157 @@
|
||||
/* edgar default CSS file */
|
||||
|
||||
body {
|
||||
font-family: "Roboto";
|
||||
font-family: monospace;
|
||||
text-align: justify;
|
||||
background-color: #373636;
|
||||
color: whitesmoke;
|
||||
font-size: 1.15em;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 55%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ol {
|
||||
width: 55%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-top: 1%;
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 90%;
|
||||
margin-top: 1%;
|
||||
margin-left: 3%;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
img {
|
||||
float: left;
|
||||
top: 5%;
|
||||
left: 5%;
|
||||
max-width: 60%;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.link-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.link-button:active {
|
||||
color: red;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: monospace;
|
||||
border-radius: 5%;
|
||||
padding: 1%;
|
||||
border-color: darkgray;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #C6D9FE;
|
||||
padding: 1%;
|
||||
}
|
||||
|
||||
ul li {
|
||||
color: #C6D9FE;
|
||||
}
|
||||
|
||||
iframe {
|
||||
background: aliceblue;
|
||||
border-radius: 15%;
|
||||
margin: 2%;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 36vw;
|
||||
height: 64vh;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-toolbar a {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
color: whitesmoke !important;
|
||||
}
|
||||
|
||||
#feed {
|
||||
width: 60vw;
|
||||
height: unset !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
float: right;
|
||||
background-color: #373636;
|
||||
color: whitesmoke;
|
||||
border: #C6D9FE solid 1px;
|
||||
}
|
||||
|
||||
.thread-post,
|
||||
.thread {
|
||||
color: whitesmoke !important;
|
||||
background-color: #373636;
|
||||
border: 1px solid darkgray;
|
||||
font-size: inherit;
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.thread-post {
|
||||
margin-left: 4%;
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: center;
|
||||
color: whitesmoke !important;
|
||||
background-color: #373636;
|
||||
border: 1px solid darkgray;
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
font-size: inherit;
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.thread-hash {
|
||||
text-align: right;
|
||||
color: whitesmoke !important;
|
||||
background-color: #373636;
|
||||
border: 1px solid darkgray;
|
||||
font-size: inherit;
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.post-body {
|
||||
text-align: left;
|
||||
color: whitesmoke !important;
|
||||
font-size: inherit;
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
#show {display:none; }
|
||||
#hide {display:block; }
|
||||
#show:target {display: block; }
|
||||
#hide:target {display: none; }
|
||||
|
||||
#shownav {display:none; }
|
||||
#hidenav {display:block; }
|
||||
#shownav:target {display: block; }
|
||||
#hidenav:target {display: none; }
|
||||
|
||||
#navbar {
|
||||
float: right;
|
||||
width: 10%;
|
||||
}
|
14
su3/su3.go
14
su3/su3.go
@@ -23,16 +23,20 @@ const (
|
||||
SigTypeRSAWithSHA384 = uint16(5)
|
||||
SigTypeRSAWithSHA512 = uint16(6)
|
||||
|
||||
ContentTypeUnknown = uint8(0)
|
||||
ContentTypeRouter = uint8(1)
|
||||
ContentTypePlugin = uint8(2)
|
||||
ContentTypeReseed = uint8(3)
|
||||
ContentTypeNews = uint8(4)
|
||||
ContentTypeUnknown = uint8(0)
|
||||
ContentTypeRouter = uint8(1)
|
||||
ContentTypePlugin = uint8(2)
|
||||
ContentTypeReseed = uint8(3)
|
||||
ContentTypeNews = uint8(4)
|
||||
ContentTypeBlocklist = uint8(5)
|
||||
|
||||
FileTypeZIP = uint8(0)
|
||||
FileTypeXML = uint8(1)
|
||||
FileTypeHTML = uint8(2)
|
||||
FileTypeXMLGZ = uint8(3)
|
||||
FileTypeTXTGZ = uint8(4)
|
||||
FileTypeDMG = uint8(5)
|
||||
FileTypeEXE = uint8(6)
|
||||
|
||||
magicBytes = "I2Psu3"
|
||||
)
|
||||
|
Reference in New Issue
Block a user