Compare commits
59 Commits
v0.0.7
...
make-a-plu
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 |
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.idea
|
||||||
|
.git
|
||||||
|
.gitlab-ci.yml
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# CI cache folder storing docker images
|
||||||
|
ci-exports
|
||||||
|
|
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
|
12
Makefile
12
Makefile
@@ -135,3 +135,15 @@ docker-homerun:
|
|||||||
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed:z \
|
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed:z \
|
||||||
eyedeekay/reseed \
|
eyedeekay/reseed \
|
||||||
--signer=hankhill19580@gmail.com
|
--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
|
||||||
|
|
||||||
|
24
README.md
24
README.md
@@ -10,7 +10,7 @@ If you have go installed you can download, build, and install this tool with `go
|
|||||||
|
|
||||||
```
|
```
|
||||||
go get i2pgit.org/idk/reseed-tools
|
go get i2pgit.org/idk/reseed-tools
|
||||||
i2p-tools -h
|
reseed-tools -h
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -76,13 +76,13 @@ work for you. In that case, just copy-and-paste:
|
|||||||
### Locally behind a webserver (reverse proxy setup), preferred:
|
### Locally behind a webserver (reverse proxy setup), preferred:
|
||||||
|
|
||||||
```
|
```
|
||||||
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
|
reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
|
||||||
```
|
```
|
||||||
|
|
||||||
### Without a webserver, standalone with TLS support
|
### Without a webserver, standalone with TLS support
|
||||||
|
|
||||||
```
|
```
|
||||||
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
|
reseed-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),
|
If this is your first time running a reseed server (ie. you don't have any existing keys),
|
||||||
@@ -103,25 +103,25 @@ Requires ```go mod``` and at least go 1.13. To build the idk/reseed-tools
|
|||||||
fork, from anywhere:
|
fork, from anywhere:
|
||||||
|
|
||||||
git clone https://i2pgit.org/idk/reseed-tools
|
git clone https://i2pgit.org/idk/reseed-tools
|
||||||
cd i2p-tools-1
|
cd reseed-tools
|
||||||
make build
|
make build
|
||||||
|
|
||||||
### Without a webserver, standalone, self-supervising(Automatic restarts)
|
### Without a webserver, standalone, self-supervising(Automatic restarts)
|
||||||
|
|
||||||
```
|
```
|
||||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --littleboss=start
|
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --littleboss=start
|
||||||
```
|
```
|
||||||
|
|
||||||
### Without a webserver, standalone, automatic OnionV3 with TLS support
|
### Without a webserver, standalone, automatic OnionV3 with TLS support
|
||||||
|
|
||||||
```
|
```
|
||||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
|
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
|
||||||
```
|
```
|
||||||
|
|
||||||
### Without a webserver, standalone, serve P2P with LibP2P
|
### Without a webserver, standalone, serve P2P with LibP2P
|
||||||
|
|
||||||
```
|
```
|
||||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
|
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
|
||||||
```
|
```
|
||||||
|
|
||||||
### Without a webserver, standalone, upload a single signed .su3 to github
|
### Without a webserver, standalone, upload a single signed .su3 to github
|
||||||
@@ -129,29 +129,29 @@ fork, from anywhere:
|
|||||||
* This one isn't working yet, I'll get to it eventually, I've got a cooler idea now.
|
* This one isn't working yet, I'll get to it eventually, I've got a cooler idea now.
|
||||||
|
|
||||||
```
|
```
|
||||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=i2p-tools-1 --ghuser=eyedeekay
|
./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
|
### Without a webserver, standalone, in-network reseed
|
||||||
|
|
||||||
```
|
```
|
||||||
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
|
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
|
||||||
```
|
```
|
||||||
|
|
||||||
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS
|
### 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
|
./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
|
### 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
|
./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
|
### 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 --littleboss=start
|
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --littleboss=start
|
||||||
```
|
```
|
||||||
|
@@ -133,6 +133,15 @@ func NewReseedCommand() cli.Command {
|
|||||||
Value: "start",
|
Value: "start",
|
||||||
Usage: "Self-Supervise this application",
|
Usage: "Self-Supervise this application",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "acme",
|
||||||
|
Usage: "Automatically generate a TLS certificate with the ACME protocol, defaults to Let's Encrypt",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "acmeserver",
|
||||||
|
Value: "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||||
|
Usage: "Use this server to issue a certificate with the ACME protocol",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,13 +217,53 @@ func reseedAction(c *cli.Context) {
|
|||||||
var i2pTlsCert, i2pTlsKey string
|
var i2pTlsCert, i2pTlsKey string
|
||||||
var i2pkey i2pkeys.I2PKeys
|
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")
|
||||||
|
// 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") {
|
if c.Bool("i2p") {
|
||||||
var err error
|
var err error
|
||||||
i2pkey, err = LoadKeys("reseed.i2pkeys", c)
|
i2pkey, err = LoadKeys("reseed.i2pkeys", c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
if i2pTlsHost == "" {
|
||||||
i2pTlsHost = i2pkey.Addr().Base32()
|
i2pTlsHost = i2pkey.Addr().Base32()
|
||||||
|
}
|
||||||
if i2pTlsHost != "" {
|
if i2pTlsHost != "" {
|
||||||
// if no key is specified, default to the host.pem in the current dir
|
// if no key is specified, default to the host.pem in the current dir
|
||||||
if i2pTlsKey == "" {
|
if i2pTlsKey == "" {
|
||||||
@@ -250,7 +299,9 @@ func reseedAction(c *cli.Context) {
|
|||||||
}
|
}
|
||||||
ok = []byte(key.PrivateKey())
|
ok = []byte(key.PrivateKey())
|
||||||
}
|
}
|
||||||
|
if onionTlsHost == "" {
|
||||||
onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
|
onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
|
||||||
|
}
|
||||||
err = ioutil.WriteFile(c.String("onionKey"), ok, 0644)
|
err = ioutil.WriteFile(c.String("onionKey"), ok, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err.Error())
|
log.Fatalln(err.Error())
|
||||||
@@ -275,27 +326,6 @@ func reseedAction(c *cli.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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?
|
|
||||||
auto := c.Bool("yes")
|
|
||||||
err := checkOrNewTLSCert(tlsHost, &tlsCert, &tlsKey, auto)
|
|
||||||
if nil != err {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reloadIntvl, err := time.ParseDuration(c.String("interval"))
|
reloadIntvl, err := time.ParseDuration(c.String("interval"))
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Printf("'%s' is not a valid time interval.\n", reloadIntvl)
|
fmt.Printf("'%s' is not a valid time interval.\n", reloadIntvl)
|
||||||
@@ -362,7 +392,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 := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||||
server.Reseeder = reseeder
|
server.Reseeder = reseeder
|
||||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||||
@@ -391,7 +421,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 := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||||
server.Reseeder = reseeder
|
server.Reseeder = reseeder
|
||||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||||
@@ -428,7 +458,7 @@ func makeRandomHost(port int) (host.Host, error) {
|
|||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func reseedP2P(c *cli.Context, reseeder reseed.Reseeder) {
|
func reseedP2P(c *cli.Context, reseeder *reseed.ReseederImpl) {
|
||||||
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||||
server.Reseeder = reseeder
|
server.Reseeder = reseeder
|
||||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||||
@@ -466,7 +496,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 := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||||
server.Reseeder = reseeder
|
server.Reseeder = reseeder
|
||||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||||
@@ -541,7 +571,7 @@ func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder rese
|
|||||||
log.Printf("Onion server started on %s\n", server.Addr)
|
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 := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
|
||||||
server.Reseeder = reseeder
|
server.Reseeder = reseeder
|
||||||
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
|
||||||
|
188
cmd/utils.go
188
cmd/utils.go
@@ -2,10 +2,12 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
@@ -18,6 +20,13 @@ import (
|
|||||||
|
|
||||||
"i2pgit.org/idk/reseed-tools/reseed"
|
"i2pgit.org/idk/reseed-tools/reseed"
|
||||||
"i2pgit.org/idk/reseed-tools/su3"
|
"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) {
|
func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
|
||||||
@@ -35,6 +44,24 @@ func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
|
|||||||
return privKey, nil
|
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 {
|
func signerFile(signerID string) string {
|
||||||
return strings.Replace(signerID, "@", "_at_", 1)
|
return strings.Replace(signerID, "@", "_at_", 1)
|
||||||
}
|
}
|
||||||
@@ -60,6 +87,165 @@ func getOrNewSigningCert(signerKey *string, signerID string, auto bool) (*rsa.Pr
|
|||||||
return loadPrivateKey(*signerKey)
|
return loadPrivateKey(*signerKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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 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 {
|
func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error {
|
||||||
_, certErr := os.Stat(*tlsCert)
|
_, certErr := os.Stat(*tlsCert)
|
||||||
_, keyErr := os.Stat(*tlsKey)
|
_, keyErr := os.Stat(*tlsKey)
|
||||||
@@ -71,7 +257,7 @@ func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error
|
|||||||
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
|
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if auto {
|
if !auto {
|
||||||
fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost)
|
fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost)
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
input, _ := reader.ReadString('\n')
|
input, _ := reader.ReadString('\n')
|
||||||
|
@@ -6,4 +6,13 @@ your attention, we're going to take this opportunity to tell you a little about
|
|||||||
network which uses "Garlic Routing" to maintain privacy. Reseed nodes help you get connected to I2P for the first time,
|
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.
|
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 here:](https://geti2p.net/en/docs/reseed)
|
||||||
|
- [Learn how to run a reseed here:](https://geti2p.net/en/get-involved/guides/reseed)
|
||||||
|
- [Read the reseed server code and learn about more reseed options here:](https://i2pgit.org/idk/reseed-tools)
|
||||||
|
|
||||||
|
### Here on purpose? Here's a one-time link to a reseed bundle for you.
|
||||||
|
@@ -13,3 +13,25 @@ img {
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: blue;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1em;
|
||||||
|
font-family: serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-button:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-button:active {
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
|
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
cp -r /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/content ./content
|
cp -r /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/content ./content
|
||||||
|
|
||||||
/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/i2p-tools-1 reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb $@
|
/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/reseed-tools reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb $@
|
||||||
|
27
go.mod
27
go.mod
@@ -3,36 +3,17 @@ module i2pgit.org/idk/reseed-tools
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/btcsuite/btcd v0.21.0-beta // indirect
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
|
||||||
github.com/cretz/bine v0.1.0
|
github.com/cretz/bine v0.1.0
|
||||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
|
||||||
github.com/eyedeekay/ramp v0.0.0-20190429201811-305b382042ab // indirect
|
|
||||||
github.com/eyedeekay/sam3 v0.32.32
|
github.com/eyedeekay/sam3 v0.32.32
|
||||||
github.com/gomodule/redigo v1.8.3 // indirect
|
github.com/go-acme/lego/v4 v4.3.1
|
||||||
github.com/google/gopacket v1.1.19 // indirect
|
|
||||||
github.com/google/uuid v1.1.2 // indirect
|
|
||||||
github.com/gorilla/handlers v1.5.1
|
github.com/gorilla/handlers v1.5.1
|
||||||
github.com/jackpal/gateway v1.0.6 // indirect
|
|
||||||
github.com/justinas/alice v1.2.0
|
github.com/justinas/alice v1.2.0
|
||||||
github.com/koron/go-ssdp v0.0.2 // indirect
|
|
||||||
github.com/libp2p/go-libp2p v0.13.0
|
github.com/libp2p/go-libp2p v0.13.0
|
||||||
github.com/libp2p/go-libp2p-core v0.8.0
|
github.com/libp2p/go-libp2p-core v0.8.0
|
||||||
github.com/libp2p/go-libp2p-gostream v0.3.0
|
github.com/libp2p/go-libp2p-gostream v0.3.1
|
||||||
github.com/libp2p/go-libp2p-http v0.2.0
|
github.com/libp2p/go-libp2p-http v0.2.0
|
||||||
github.com/libp2p/go-libp2p-noise v0.1.2 // indirect
|
github.com/throttled/throttled/v2 v2.7.1
|
||||||
github.com/libp2p/go-netroute v0.1.4 // indirect
|
|
||||||
github.com/libp2p/go-sockaddr v0.1.0 // indirect
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
|
||||||
github.com/throttled/throttled v2.2.4+incompatible
|
|
||||||
github.com/urfave/cli v1.22.5
|
github.com/urfave/cli v1.22.5
|
||||||
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 // indirect
|
|
||||||
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19
|
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19
|
||||||
go.opencensus.io v0.22.5 // indirect
|
golang.org/x/text v0.3.5
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
|
||||||
go.uber.org/zap v1.16.0 // indirect
|
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect
|
|
||||||
golang.org/x/text v0.3.4
|
|
||||||
)
|
)
|
||||||
|
@@ -47,7 +47,7 @@ func ContentPath() (string, error) {
|
|||||||
return filepath.Join(exPath, "content"), nil
|
return filepath.Join(exPath, "content"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleARealBrowser(w http.ResponseWriter, r *http.Request) {
|
func (srv *Server) HandleARealBrowser(w http.ResponseWriter, r *http.Request) {
|
||||||
if ContentPathError != nil {
|
if ContentPathError != nil {
|
||||||
http.Error(w, "403 Forbidden", http.StatusForbidden)
|
http.Error(w, "403 Forbidden", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
@@ -73,6 +73,12 @@ func HandleARealBrowser(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("Content-Type", "text/html")
|
w.Header().Set("Content-Type", "text/html")
|
||||||
w.Write([]byte(header))
|
w.Write([]byte(header))
|
||||||
HandleALocalizedFile(w, base.String())
|
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">
|
||||||
|
Bundle
|
||||||
|
</button>
|
||||||
|
</form></li></ul>`))
|
||||||
w.Write([]byte(footer))
|
w.Write([]byte(footer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +122,7 @@ func HandleALocalizedFile(w http.ResponseWriter, dirPath string) {
|
|||||||
f = append(f, []byte(`<div id="`+trimmedName+`">`)...)
|
f = append(f, []byte(`<div id="`+trimmedName+`">`)...)
|
||||||
f = append(f, []byte(md.RenderToString(b))...)
|
f = append(f, []byte(md.RenderToString(b))...)
|
||||||
f = append(f, []byte(`</div>`)...)
|
f = append(f, []byte(`</div>`)...)
|
||||||
|
|
||||||
}
|
}
|
||||||
CachedLanguagePages[dirPath] = string(f)
|
CachedLanguagePages[dirPath] = string(f)
|
||||||
w.Write([]byte(CachedLanguagePages[dirPath]))
|
w.Write([]byte(CachedLanguagePages[dirPath]))
|
||||||
|
@@ -3,6 +3,7 @@ package reseed
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -20,8 +21,8 @@ import (
|
|||||||
"github.com/libp2p/go-libp2p-core/host"
|
"github.com/libp2p/go-libp2p-core/host"
|
||||||
gostream "github.com/libp2p/go-libp2p-gostream"
|
gostream "github.com/libp2p/go-libp2p-gostream"
|
||||||
p2phttp "github.com/libp2p/go-libp2p-http"
|
p2phttp "github.com/libp2p/go-libp2p-http"
|
||||||
"github.com/throttled/throttled"
|
throttled "github.com/throttled/throttled/v2"
|
||||||
"github.com/throttled/throttled/store"
|
"github.com/throttled/throttled/v2/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -34,9 +35,10 @@ type Server struct {
|
|||||||
I2PSession *sam3.StreamSession
|
I2PSession *sam3.StreamSession
|
||||||
I2PListener *sam3.StreamListener
|
I2PListener *sam3.StreamListener
|
||||||
I2PKeys i2pkeys.I2PKeys
|
I2PKeys i2pkeys.I2PKeys
|
||||||
Reseeder Reseeder
|
Reseeder *ReseederImpl
|
||||||
Blacklist *Blacklist
|
Blacklist *Blacklist
|
||||||
OnionListener *tor.OnionService
|
OnionListener *tor.OnionService
|
||||||
|
acceptables map[string]time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(prefix string, trustProxy bool) *Server {
|
func NewServer(prefix string, trustProxy bool) *Server {
|
||||||
@@ -65,6 +67,7 @@ func NewServer(prefix string, trustProxy bool) *Server {
|
|||||||
server := Server{Server: h, Reseeder: nil}
|
server := Server{Server: h, Reseeder: nil}
|
||||||
|
|
||||||
th := throttled.RateLimit(throttled.PerHour(4), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000))
|
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()
|
middlewareChain := alice.New()
|
||||||
if trustProxy {
|
if trustProxy {
|
||||||
@@ -79,13 +82,85 @@ func NewServer(prefix string, trustProxy bool) *Server {
|
|||||||
})
|
})
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle("/", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, browsingMiddleware).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)))
|
mux.Handle(prefix+"/i2pseeds.su3", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, verifyMiddleware, th.Throttle).Then(http.HandlerFunc(server.reseedHandler)))
|
||||||
server.Handler = mux
|
server.Handler = mux
|
||||||
|
|
||||||
return &server
|
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 {
|
func (srv *Server) ListenAndServe() error {
|
||||||
addr := srv.Addr
|
addr := srv.Addr
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
@@ -245,7 +320,7 @@ func (srv *Server) ListenAndServeI2P(samaddr string, I2PKeys i2pkeys.I2PKeys) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
return srv.Serve(srv.I2PListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,10 +366,13 @@ func loggingMiddleware(next http.Handler) http.Handler {
|
|||||||
return handlers.CombinedLoggingHandler(os.Stdout, next)
|
return handlers.CombinedLoggingHandler(os.Stdout, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
func browsingMiddleware(next http.Handler) http.Handler {
|
func (srv *Server) browsingMiddleware(next http.Handler) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if srv.CheckAcceptable(r.FormValue("onetime")) {
|
||||||
|
srv.reseedHandler(w, r)
|
||||||
|
}
|
||||||
if i2pUserAgent != r.UserAgent() {
|
if i2pUserAgent != r.UserAgent() {
|
||||||
HandleARealBrowser(w, r)
|
srv.HandleARealBrowser(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
@@ -33,13 +33,13 @@ func (p Peer) Hash() int {
|
|||||||
return int(crc32.ChecksumIEEE(c))
|
return int(crc32.ChecksumIEEE(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reseeder interface {
|
/*type Reseeder interface {
|
||||||
// get an su3 file (bytes) for a peer
|
// get an su3 file (bytes) for a peer
|
||||||
PeerSu3Bytes(peer Peer) ([]byte, error)
|
PeerSu3Bytes(peer Peer) ([]byte, error)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
type ReseederImpl struct {
|
type ReseederImpl struct {
|
||||||
netdb NetDbProvider
|
netdb *LocalNetDbImpl
|
||||||
su3s chan [][]byte
|
su3s chan [][]byte
|
||||||
|
|
||||||
SigningKey *rsa.PrivateKey
|
SigningKey *rsa.PrivateKey
|
||||||
@@ -49,7 +49,7 @@ type ReseederImpl struct {
|
|||||||
NumSu3 int
|
NumSu3 int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReseeder(netdb NetDbProvider) *ReseederImpl {
|
func NewReseeder(netdb *LocalNetDbImpl) *ReseederImpl {
|
||||||
return &ReseederImpl{
|
return &ReseederImpl{
|
||||||
netdb: netdb,
|
netdb: netdb,
|
||||||
su3s: make(chan [][]byte),
|
su3s: make(chan [][]byte),
|
||||||
@@ -224,10 +224,10 @@ func (rs *ReseederImpl) createSu3(seeds []routerInfo) (*su3.File, error) {
|
|||||||
return su3File, nil
|
return su3File, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetDbProvider interface {
|
/*type NetDbProvider interface {
|
||||||
// Get all router infos
|
// Get all router infos
|
||||||
RouterInfos() ([]routerInfo, error)
|
RouterInfos() ([]routerInfo, error)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
type LocalNetDbImpl struct {
|
type LocalNetDbImpl struct {
|
||||||
Path string
|
Path string
|
||||||
|
Reference in New Issue
Block a user