Skip to content

Commit

Permalink
Merge pull request #12 from bitvora/dev-rateLimits
Browse files Browse the repository at this point in the history
Rate Limiter, Public Pages
  • Loading branch information
barrydeen authored Sep 25, 2024
2 parents b53bb28 + b268b1e commit b7d4b82
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 14 deletions.
57 changes: 47 additions & 10 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ PRIVATE_RELAY_NPUB="npub1utx00neqgqln72j22kej3ux7803c2k986henvvha4thuwfkper4s7r5
PRIVATE_RELAY_DESCRIPTION="A safe place to store my drafts and ecash"
PRIVATE_RELAY_ICON="https://i.nostr.build/6G6wW.gif"

## Private Relay Rate Limiters
PRIVATE_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL=50
PRIVATE_RELAY_EVENT_IP_LIMITER_INTERVAL=1
PRIVATE_RELAY_EVENT_IP_LIMITER_MAX_TOKENS=100
PRIVATE_RELAY_ALLOW_EMPTY_FILTERS=true
PRIVATE_RELAY_ALLOW_COMPLEX_FILTERS=true
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL=3
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_INTERVAL=5
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS=9

## Chat Relay Settings
CHAT_RELAY_NAME="utxo's chat relay"
CHAT_RELAY_NPUB="npub1utx00neqgqln72j22kej3ux7803c2k986henvvha4thuwfkper4s7r50e8"
Expand All @@ -16,39 +26,66 @@ CHAT_RELAY_WOT_DEPTH=3
CHAT_RELAY_WOT_REFRESH_INTERVAL_HOURS=24
CHAT_RELAY_MINIMUM_FOLLOWERS=3

## Chat Relay Rate Limiters
CHAT_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL=50
CHAT_RELAY_EVENT_IP_LIMITER_INTERVAL=1
CHAT_RELAY_EVENT_IP_LIMITER_MAX_TOKENS=100
CHAT_RELAY_ALLOW_EMPTY_FILTERS=false
CHAT_RELAY_ALLOW_COMPLEX_FILTERS=false
CHAT_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL=3
CHAT_RELAY_CONNECTION_RATE_LIMITER_INTERVAL=3
CHAT_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS=9

## Outbox Relay Settings
OUTBOX_RELAY_NAME="utxo's outbox relay"
OUTBOX_RELAY_NPUB="npub1utx00neqgqln72j22kej3ux7803c2k986henvvha4thuwfkper4s7r50e8"
OUTBOX_RELAY_DESCRIPTION="a relay for public messages"
OUTBOX_RELAY_ICON="https://i.nostr.build/6G6wW.gif"

## Outbox Relay Rate Limiters
OUTBOX_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL=10
OUTBOX_RELAY_EVENT_IP_LIMITER_INTERVAL=60
OUTBOX_RELAY_EVENT_IP_LIMITER_MAX_TOKENS=100
OUTBOX_RELAY_ALLOW_EMPTY_FILTERS=false
OUTBOX_RELAY_ALLOW_COMPLEX_FILTERS=false
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL=3
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_INTERVAL=1
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS=9

## Inbox Relay Settings
INBOX_RELAY_NAME="utxo's inbox relay"
INBOX_RELAY_NPUB="npub1utx00neqgqln72j22kej3ux7803c2k986henvvha4thuwfkper4s7r50e8"
INBOX_RELAY_DESCRIPTION="send your interactions with my notes here"
INBOX_RELAY_ICON="https://i.nostr.build/6G6wW.gif"
INBOX_PULL_INTERVAL_SECONDS=600

## Inbox Relay Rate Limiters
INBOX_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL=10
INBOX_RELAY_EVENT_IP_LIMITER_INTERVAL=1
INBOX_RELAY_EVENT_IP_LIMITER_MAX_TOKENS=20
INBOX_RELAY_ALLOW_EMPTY_FILTERS=false
INBOX_RELAY_ALLOW_COMPLEX_FILTERS=false
INBOX_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL=3
INBOX_RELAY_CONNECTION_RATE_LIMITER_INTERVAL=1
INBOX_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS=9


## Import Settings
IMPORT_START_DATE="2023-01-20"
IMPORT_QUERY_INTERVAL_SECONDS=600
IMPORT_SEED_RELAYS="relay.damus.io,nos.lol,relay.nostr.band,relay.snort.social,nostr.land,nostr.mom,relay.nos.social,relay.primal.net,relay.nostr.bg,no.str.cr,nostr21.com,nostrue.com,relay.siamstr.com,wot.utxo.one,nostrelites.org,wot.nostr.party,wot.sovbit.host,wot.girino.org,relay.lnau.net,wot.siamstr.com,wot.sudocarlos.com,relay.otherstuff.fyi,relay.lexingtonbitcoin.org,wot.azzamo.net,wot.swarmstr.com,zap.watch,satsage.xyz,wons.calva.dev"
IMPORT_SEED_RELAYS_FILE=""
IMPORT_SEED_RELAYS_FILE="relays_blastr.json"

## Backup Settings
BACKUP_PROVIDER="aws"
BACKUP_INTERVAL_HOURS=24

## AWS Backup Settings - REQUIRED IF BACKUP_PROVIDER="aws"
AWS_ACCESS_KEY_ID="AKIA"
AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
AWS_REGION="us-west-2"
AWS_BUCKET_NAME="utxo-relay-backups"
AWS_ACCESS_KEY_ID="access"
AWS_SECRET_ACCESS_KEY="secret"
AWS_REGION="us-east-1"
AWS_BUCKET_NAME="backups"

## Blastr Settings
BLASTR_RELAYS="relay.damus.io,nos.lol,relay.nostr.band,relay.snort.social,nostr.land,nostr.mom,relay.nos.social,relay.primal.net,relay.nostr.bg,no.str.cr,nostr21.com,nostrue.com,relay.siamstr.com,wot.utxo.one,nostrelites.org,wot.nostr.party,wot.sovbit.host,wot.girino.org,relay.lnau.net,wot.siamstr.com,wot.sudocarlos.com,relay.otherstuff.fyi,relay.lexingtonbitcoin.org,wot.azzamo.net,wot.swarmstr.com,zap.watch,satsage.xyz,wons.calva.dev"
BLASTR_RELAYS_FILE=""

## OPTIONAL: Docker UID and GID - should be the same as the user running the docker container
DOCKER_UID=1000
DOCKER_GID=1000
BLASTR_RELAYS_FILE="relays_blastr.json"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.env
relays_import.json
relays_blastr.json
haven
15 changes: 13 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package main

import (
"encoding/json"
"io/ioutil"
"log"
"os"
"strconv"
"strings"
"encoding/json"
"io/ioutil"

"github.com/joho/godotenv"
)
Expand Down Expand Up @@ -146,6 +146,17 @@ func getEnvInt(key string, defaultValue int) int {
return defaultValue
}

func getEnvBool(key string, defaultValue bool) bool {
if value, ok := os.LookupEnv(key); ok {
boolValue, err := strconv.ParseBool(value)
if err != nil {
panic(err)
}
return boolValue
}
return defaultValue
}

var art = `
██╗ ██╗ █████╗ ██╗ ██╗███████╗███╗ ██╗
██║ ██║██╔══██╗██║ ██║██╔════╝████╗ ██║
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.tor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ services:
- "./db:/app/db"
- "./haven:/app/haven"
ports:
- "3335"
- "3355"
user: "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"

tor:
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ services:
- "./db:/app/db"
- "./haven:/app/haven"
ports:
- "3335:3335"
- "3355:3355"
user: "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"
Binary file added haven
Binary file not shown.
106 changes: 106 additions & 0 deletions init.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package main

import (
"time"

"github.com/fiatjaf/eventstore/lmdb"
"github.com/fiatjaf/khatru"
"github.com/fiatjaf/khatru/policies"
)

var (
Expand Down Expand Up @@ -66,6 +69,8 @@ func initRelays() {
panic(err)
}

initRelayLimits()

privateRelay.Info.Name = config.PrivateRelayName
privateRelay.Info.PubKey = nPubToPubkey(config.PrivateRelayNpub)
privateRelay.Info.Description = config.PrivateRelayDescription
Expand All @@ -74,6 +79,31 @@ func initRelays() {
privateRelay.Info.Software = config.RelaySoftware
privateRelay.ServiceURL = "https://" + config.RelayURL + "/private"

if !privateRelayLimits.AllowEmptyFilters {
privateRelay.RejectFilter = append(privateRelay.RejectFilter, policies.NoEmptyFilters)
}

if !privateRelayLimits.AllowComplexFilters {
privateRelay.RejectFilter = append(privateRelay.RejectFilter, policies.NoComplexFilters)
}

privateRelay.RejectEvent = append(privateRelay.RejectEvent,
policies.RejectEventsWithBase64Media,
policies.EventIPRateLimiter(
privateRelayLimits.EventIPLimiterTokensPerInterval,
time.Minute*time.Duration(privateRelayLimits.EventIPLimiterInterval),
privateRelayLimits.EventIPLimiterMaxTokens,
),
)

privateRelay.RejectConnection = append(privateRelay.RejectConnection,
policies.ConnectionRateLimiter(
privateRelayLimits.ConnectionRateLimiterTokensPerInterval,
time.Minute*time.Duration(privateRelayLimits.ConnectionRateLimiterInterval),
privateRelayLimits.ConnectionRateLimiterMaxTokens,
),
)

chatRelay.Info.Name = config.ChatRelayName
chatRelay.Info.PubKey = nPubToPubkey(config.ChatRelayNpub)
chatRelay.Info.Description = config.ChatRelayDescription
Expand All @@ -82,18 +112,94 @@ func initRelays() {
chatRelay.Info.Software = config.RelaySoftware
chatRelay.ServiceURL = "https://" + config.RelayURL + "/chat"

if !chatRelayLimits.AllowEmptyFilters {
chatRelay.RejectFilter = append(chatRelay.RejectFilter, policies.NoEmptyFilters)
}

if !chatRelayLimits.AllowComplexFilters {
chatRelay.RejectFilter = append(chatRelay.RejectFilter, policies.NoComplexFilters)
}

chatRelay.RejectEvent = append(chatRelay.RejectEvent,
policies.RejectEventsWithBase64Media,
policies.EventIPRateLimiter(
chatRelayLimits.EventIPLimiterTokensPerInterval,
time.Minute*time.Duration(chatRelayLimits.EventIPLimiterInterval),
chatRelayLimits.EventIPLimiterMaxTokens,
),
)

chatRelay.RejectConnection = append(chatRelay.RejectConnection,
policies.ConnectionRateLimiter(
chatRelayLimits.ConnectionRateLimiterTokensPerInterval,
time.Minute*time.Duration(chatRelayLimits.ConnectionRateLimiterInterval),
chatRelayLimits.ConnectionRateLimiterMaxTokens,
),
)

outboxRelay.Info.Name = config.OutboxRelayName
outboxRelay.Info.PubKey = nPubToPubkey(config.OutboxRelayNpub)
outboxRelay.Info.Description = config.OutboxRelayDescription
outboxRelay.Info.Icon = config.OutboxRelayIcon
outboxRelay.Info.Version = config.RelayVersion
outboxRelay.Info.Software = config.RelaySoftware

if !outboxRelayLimits.AllowEmptyFilters {
outboxRelay.RejectFilter = append(outboxRelay.RejectFilter, policies.NoEmptyFilters)
}

if !outboxRelayLimits.AllowComplexFilters {
outboxRelay.RejectFilter = append(outboxRelay.RejectFilter, policies.NoComplexFilters)
}

outboxRelay.RejectEvent = append(outboxRelay.RejectEvent,
policies.RejectEventsWithBase64Media,
policies.EventIPRateLimiter(
outboxRelayLimits.EventIPLimiterTokensPerInterval,
time.Minute*time.Duration(outboxRelayLimits.EventIPLimiterInterval),
outboxRelayLimits.EventIPLimiterMaxTokens,
),
)

outboxRelay.RejectConnection = append(outboxRelay.RejectConnection,
policies.ConnectionRateLimiter(
outboxRelayLimits.ConnectionRateLimiterTokensPerInterval,
time.Minute*time.Duration(outboxRelayLimits.ConnectionRateLimiterInterval),
outboxRelayLimits.ConnectionRateLimiterMaxTokens,
),
)

inboxRelay.Info.Name = config.InboxRelayName
inboxRelay.Info.PubKey = nPubToPubkey(config.InboxRelayNpub)
inboxRelay.Info.Description = config.InboxRelayDescription
inboxRelay.Info.Icon = config.InboxRelayIcon
inboxRelay.Info.Version = config.RelayVersion
inboxRelay.Info.Software = config.RelaySoftware
inboxRelay.ServiceURL = "https://" + config.RelayURL + "/inbox"

if !inboxRelayLimits.AllowEmptyFilters {
inboxRelay.RejectFilter = append(inboxRelay.RejectFilter, policies.NoEmptyFilters)
}

if !inboxRelayLimits.AllowComplexFilters {
inboxRelay.RejectFilter = append(inboxRelay.RejectFilter, policies.NoComplexFilters)
}

inboxRelay.RejectEvent = append(inboxRelay.RejectEvent,
policies.RejectEventsWithBase64Media,
policies.EventIPRateLimiter(
inboxRelayLimits.EventIPLimiterTokensPerInterval,
time.Minute*time.Duration(inboxRelayLimits.EventIPLimiterInterval),
inboxRelayLimits.EventIPLimiterMaxTokens,
),
)

inboxRelay.RejectConnection = append(inboxRelay.RejectConnection,
policies.ConnectionRateLimiter(
inboxRelayLimits.ConnectionRateLimiterTokensPerInterval,
time.Minute*time.Duration(inboxRelayLimits.ConnectionRateLimiterInterval),
inboxRelayLimits.ConnectionRateLimiterMaxTokens,
),
)

}
Loading

0 comments on commit b7d4b82

Please sign in to comment.