mirror of
https://github.com/asmogo/nws.git
synced 2025-01-18 10:01:33 +00:00
Merge branch 'main' into lint
This commit is contained in:
commit
fa8a21e044
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
localhost.crt
|
localhost.crt
|
||||||
localhost.key
|
localhost.key
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
nostr
|
nostr
|
@ -31,9 +31,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
nostr:
|
nostr:
|
||||||
environment:
|
environment:
|
||||||
- NOSTR_RELAYS=ws://nostr-relay:8080
|
- NOSTR_RELAYS=ws://nostr-relay:7777
|
||||||
- NOSTR_PRIVATE_KEY=
|
- NOSTR_PRIVATE_KEY=
|
||||||
- BACKEND_HOST=mint:3338
|
- BACKEND_HOST=mint:3338
|
||||||
|
depends_on:
|
||||||
|
- mint
|
||||||
|
- nostr
|
||||||
exit-https:
|
exit-https:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@ -43,9 +46,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
nostr:
|
nostr:
|
||||||
environment:
|
environment:
|
||||||
- NOSTR_RELAYS=ws://nostr-relay:8080
|
- NOSTR_RELAYS=ws://nostr-relay:7777
|
||||||
- NOSTR_PRIVATE_KEY=
|
- NOSTR_PRIVATE_KEY=
|
||||||
- BACKEND_HOST=:4443
|
- BACKEND_HOST=:4443
|
||||||
|
depends_on:
|
||||||
|
- mint
|
||||||
|
- nostr
|
||||||
entry:
|
entry:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@ -56,16 +62,17 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
nostr:
|
nostr:
|
||||||
environment:
|
environment:
|
||||||
- NOSTR_RELAYS=ws://nostr-relay:8080
|
- NOSTR_RELAYS=ws://nostr-relay:7777
|
||||||
|
depends_on:
|
||||||
|
- nostr
|
||||||
nostr:
|
nostr:
|
||||||
image: scsibug/nostr-rs-relay:latest
|
image: carroarmato0/strfry:latest
|
||||||
container_name: nostr-relay
|
container_name: nostr-relay
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 7777:7777
|
||||||
networks:
|
networks:
|
||||||
nostr:
|
nostr:
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./nostr/data:/usr/src/app/db:Z
|
- ./strfry/data:/app/strfry-db/:Z
|
||||||
- ./nostr/config/config.toml:/usr/src/app/config.toml:ro,Z
|
- ./strfry/strfry.conf:/app/strfry.conf:ro,Z
|
||||||
user: 100:100
|
|
||||||
|
@ -61,15 +61,10 @@ func NewExit(ctx context.Context, exitNodeConfig *config.ExitConfig) *Exit {
|
|||||||
// generate new private key
|
// generate new private key
|
||||||
exitNodeConfig.NostrPrivateKey = nostr.GeneratePrivateKey()
|
exitNodeConfig.NostrPrivateKey = nostr.GeneratePrivateKey()
|
||||||
slog.Warn(generateKeyMessage, "key", exitNodeConfig.NostrPrivateKey)
|
slog.Warn(generateKeyMessage, "key", exitNodeConfig.NostrPrivateKey)
|
||||||
} else {
|
|
||||||
pubKey, err := nostr.GetPublicKey(exitNodeConfig.NostrPrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
slog.Info("using public key", "key", pubKey)
|
|
||||||
}
|
}
|
||||||
// get public key from private key
|
// get public key from private key
|
||||||
pubKey, err := nostr.GetPublicKey(exitNodeConfig.NostrPrivateKey)
|
pubKey, err := nostr.GetPublicKey(exitNodeConfig.NostrPrivateKey)
|
||||||
|
slog.Info("using public key", "key", pubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,6 @@ import (
|
|||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/asmogo/nws/protocol"
|
|
||||||
"github.com/nbd-wtf/go-nostr"
|
|
||||||
"github.com/nbd-wtf/go-nostr/nip04"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -19,14 +16,18 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/asmogo/nws/protocol"
|
||||||
|
"github.com/nbd-wtf/go-nostr"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip04"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Exit) StartReverseProxy(httpTarget string, port int32) error {
|
func (e *Exit) StartReverseProxy(httpTarget string, port int32) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ev := e.pool.QuerySingle(ctx, e.config.NostrRelays, nostr.Filter{
|
ev := e.pool.QuerySingle(ctx, e.config.NostrRelays, nostr.Filter{
|
||||||
Authors: []string{e.publicKey},
|
Authors: []string{e.publicKey},
|
||||||
Kinds: []int{nostr.KindTextNote},
|
Kinds: []int{protocol.KindCertificateEvent},
|
||||||
Tags: nostr.TagMap{"p": []string{e.nprofile}},
|
Tags: nostr.TagMap{"p": []string{e.publicKey}},
|
||||||
})
|
})
|
||||||
var cert tls.Certificate
|
var cert tls.Certificate
|
||||||
if ev == nil {
|
if ev == nil {
|
||||||
@ -40,8 +41,8 @@ func (e *Exit) StartReverseProxy(httpTarget string, port int32) error {
|
|||||||
// load private key from file
|
// load private key from file
|
||||||
privateKeyEvent := e.pool.QuerySingle(ctx, e.config.NostrRelays, nostr.Filter{
|
privateKeyEvent := e.pool.QuerySingle(ctx, e.config.NostrRelays, nostr.Filter{
|
||||||
Authors: []string{e.publicKey},
|
Authors: []string{e.publicKey},
|
||||||
Kinds: []int{nostr.KindEncryptedDirectMessage},
|
Kinds: []int{protocol.KindPrivateKeyEvent},
|
||||||
Tags: nostr.TagMap{"p": []string{e.nprofile}},
|
Tags: nostr.TagMap{"p": []string{e.publicKey}},
|
||||||
})
|
})
|
||||||
if privateKeyEvent == nil {
|
if privateKeyEvent == nil {
|
||||||
return fmt.Errorf("failed to find encrypted direct message")
|
return fmt.Errorf("failed to find encrypted direct message")
|
||||||
@ -125,7 +126,7 @@ func (e *Exit) createAndStoreCertificateData(ctx context.Context) (*tls.Certific
|
|||||||
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
|
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
|
||||||
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
|
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
|
||||||
// save key pem to file
|
// save key pem to file
|
||||||
err := os.WriteFile(fmt.Sprintf("%s.key", e.nprofile), keyPEM, 0644)
|
err := os.WriteFile(fmt.Sprintf("%s.key", e.publicKey), keyPEM, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -146,8 +147,8 @@ func (e *Exit) storePrivateKey(ctx context.Context, keyPEM []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
event, err := s.CreateSignedEvent(e.publicKey, nostr.KindEncryptedDirectMessage, nostr.Tags{
|
event, err := s.CreateSignedEvent(e.publicKey, protocol.KindPrivateKeyEvent, nostr.Tags{
|
||||||
nostr.Tag{"p", e.nprofile},
|
nostr.Tag{"p", e.publicKey},
|
||||||
}, protocol.WithData(keyPEM))
|
}, protocol.WithData(keyPEM))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -169,10 +170,10 @@ func (e *Exit) storeCertificate(ctx context.Context, certPEM []byte) (*tls.Certi
|
|||||||
event := nostr.Event{
|
event := nostr.Event{
|
||||||
CreatedAt: nostr.Now(),
|
CreatedAt: nostr.Now(),
|
||||||
PubKey: e.publicKey,
|
PubKey: e.publicKey,
|
||||||
Kind: nostr.KindTextNote,
|
Kind: protocol.KindCertificateEvent,
|
||||||
Content: string(certPEM),
|
Content: string(certPEM),
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
nostr.Tag{"p", e.nprofile},
|
nostr.Tag{"p", e.publicKey},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := event.Sign(e.config.NostrPrivateKey)
|
err := event.Sign(e.config.NostrPrivateKey)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/asmogo/nws/protocol"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,9 +19,8 @@ func (e *Exit) announceExitNode(ctx context.Context) error {
|
|||||||
event := nostr.Event{
|
event := nostr.Event{
|
||||||
PubKey: e.publicKey,
|
PubKey: e.publicKey,
|
||||||
CreatedAt: nostr.Now(),
|
CreatedAt: nostr.Now(),
|
||||||
Kind: nostr.KindTextNote,
|
Kind: protocol.KindAnnouncementEvent,
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
nostr.Tag{"n", "nws"},
|
|
||||||
nostr.Tag{"expiration", strconv.FormatInt(time.Now().Add(time.Second*10).Unix(), 20)},
|
nostr.Tag{"expiration", strconv.FormatInt(time.Now().Add(time.Second*10).Unix(), 20)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ package netstr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/asmogo/nws/protocol"
|
||||||
|
"github.com/nbd-wtf/go-nostr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NostrDNS does not resolve anything
|
// NostrDNS does not resolve anything
|
||||||
@ -36,9 +38,8 @@ func (d NostrDNS) Resolve(ctx context.Context, name string) (context.Context, ne
|
|||||||
}
|
}
|
||||||
since := nostr.Timestamp(time.Now().Add(-time.Second * 10).Unix())
|
since := nostr.Timestamp(time.Now().Add(-time.Second * 10).Unix())
|
||||||
ev := d.pool.QuerySingle(ctx, d.nostrRelays, nostr.Filter{
|
ev := d.pool.QuerySingle(ctx, d.nostrRelays, nostr.Filter{
|
||||||
Kinds: []int{nostr.KindTextNote},
|
Kinds: []int{protocol.KindAnnouncementEvent},
|
||||||
Since: &since,
|
Since: &since,
|
||||||
Tags: nostr.TagMap{"n": []string{"nws"}},
|
|
||||||
})
|
})
|
||||||
if ev == nil {
|
if ev == nil {
|
||||||
return ctx, nil, fmt.Errorf("failed to find exit node event")
|
return ctx, nil, fmt.Errorf("failed to find exit node event")
|
||||||
|
@ -9,7 +9,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// KindEphemeralEvent represents the unique identifier for ephemeral events.
|
// KindEphemeralEvent represents the unique identifier for ephemeral events.
|
||||||
const KindEphemeralEvent int = 38333
|
const KindEphemeralEvent int = 28333
|
||||||
|
|
||||||
|
// KindAnnouncementEvent represents the unique identifier for announcement events.
|
||||||
|
const KindAnnouncementEvent int = 38333
|
||||||
|
|
||||||
|
// KindCertificateEvent represents the unique identifier for certificate events.
|
||||||
|
const KindCertificateEvent int = 38334
|
||||||
|
|
||||||
|
// KindPrivateKeyEvent represents the unique identifier for private key events.
|
||||||
|
const KindPrivateKeyEvent int = 38335
|
||||||
|
|
||||||
// EventSigner represents a signer that can create and sign events.
|
// EventSigner represents a signer that can create and sign events.
|
||||||
//
|
//
|
||||||
|
141
strfry/strfry.conf
Normal file
141
strfry/strfry.conf
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
##
|
||||||
|
## Default strfry config
|
||||||
|
##
|
||||||
|
|
||||||
|
# Directory that contains the strfry LMDB database (restart required)
|
||||||
|
db = "./strfry-db/"
|
||||||
|
|
||||||
|
dbParams {
|
||||||
|
# Maximum number of threads/processes that can simultaneously have LMDB transactions open (restart required)
|
||||||
|
maxreaders = 256
|
||||||
|
|
||||||
|
# Size of mmap() to use when loading LMDB (default is 10TB, does *not* correspond to disk-space used) (restart required)
|
||||||
|
mapsize = 10995116277760
|
||||||
|
|
||||||
|
# Disables read-ahead when accessing the LMDB mapping. Reduces IO activity when DB size is larger than RAM. (restart required)
|
||||||
|
noReadAhead = false
|
||||||
|
}
|
||||||
|
|
||||||
|
events {
|
||||||
|
# Maximum size of normalised JSON, in bytes
|
||||||
|
maxEventSize = 65536
|
||||||
|
|
||||||
|
# Events newer than this will be rejected
|
||||||
|
rejectEventsNewerThanSeconds = 900
|
||||||
|
|
||||||
|
# Events older than this will be rejected
|
||||||
|
rejectEventsOlderThanSeconds = 94608000
|
||||||
|
|
||||||
|
# Ephemeral events older than this will be rejected
|
||||||
|
rejectEphemeralEventsOlderThanSeconds = 60
|
||||||
|
|
||||||
|
# Ephemeral events will be deleted from the DB when older than this
|
||||||
|
ephemeralEventsLifetimeSeconds = 300
|
||||||
|
|
||||||
|
# Maximum number of tags allowed
|
||||||
|
maxNumTags = 2000
|
||||||
|
|
||||||
|
# Maximum size for tag values, in bytes
|
||||||
|
maxTagValSize = 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
relay {
|
||||||
|
# Interface to listen on. Use 0.0.0.0 to listen on all interfaces (restart required)
|
||||||
|
bind = "0.0.0.0"
|
||||||
|
|
||||||
|
# Port to open for the nostr websocket protocol (restart required)
|
||||||
|
port = 7777
|
||||||
|
|
||||||
|
# Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set) (restart required)
|
||||||
|
nofiles = 1000000
|
||||||
|
|
||||||
|
# HTTP header that contains the client's real IP, before reverse proxying (ie x-real-ip) (MUST be all lower-case)
|
||||||
|
realIpHeader = ""
|
||||||
|
|
||||||
|
info {
|
||||||
|
# NIP-11: Name of this server. Short/descriptive (< 30 characters)
|
||||||
|
name = "strfry default"
|
||||||
|
|
||||||
|
# NIP-11: Detailed information about relay, free-form
|
||||||
|
description = "This is a strfry instance."
|
||||||
|
|
||||||
|
# NIP-11: Administrative nostr pubkey, for contact purposes
|
||||||
|
pubkey = ""
|
||||||
|
|
||||||
|
# NIP-11: Alternative administrative contact (email, website, etc)
|
||||||
|
contact = ""
|
||||||
|
|
||||||
|
# NIP-11: URL pointing to an image to be used as an icon for the relay
|
||||||
|
icon = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Maximum accepted incoming websocket frame size (should be larger than max event) (restart required)
|
||||||
|
maxWebsocketPayloadSize = 131072
|
||||||
|
|
||||||
|
# Websocket-level PING message frequency (should be less than any reverse proxy idle timeouts) (restart required)
|
||||||
|
autoPingSeconds = 55
|
||||||
|
|
||||||
|
# If TCP keep-alive should be enabled (detect dropped connections to upstream reverse proxy)
|
||||||
|
enableTcpKeepalive = false
|
||||||
|
|
||||||
|
# How much uninterrupted CPU time a REQ query should get during its DB scan
|
||||||
|
queryTimesliceBudgetMicroseconds = 10000
|
||||||
|
|
||||||
|
# Maximum records that can be returned per filter
|
||||||
|
maxFilterLimit = 500
|
||||||
|
|
||||||
|
# Maximum number of subscriptions (concurrent REQs) a connection can have open at any time
|
||||||
|
maxSubsPerConnection = 20
|
||||||
|
|
||||||
|
writePolicy {
|
||||||
|
# If non-empty, path to an executable script that implements the writePolicy plugin logic
|
||||||
|
plugin = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
compression {
|
||||||
|
# Use permessage-deflate compression if supported by client. Reduces bandwidth, but slight increase in CPU (restart required)
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Maintain a sliding window buffer for each connection. Improves compression, but uses more memory (restart required)
|
||||||
|
slidingWindow = true
|
||||||
|
}
|
||||||
|
|
||||||
|
logging {
|
||||||
|
# Dump all incoming messages
|
||||||
|
dumpInAll = false
|
||||||
|
|
||||||
|
# Dump all incoming EVENT messages
|
||||||
|
dumpInEvents = false
|
||||||
|
|
||||||
|
# Dump all incoming REQ/CLOSE messages
|
||||||
|
dumpInReqs = false
|
||||||
|
|
||||||
|
# Log performance metrics for initial REQ database scans
|
||||||
|
dbScanPerf = false
|
||||||
|
|
||||||
|
# Log reason for invalid event rejection? Can be disabled to silence excessive logging
|
||||||
|
invalidEvents = true
|
||||||
|
}
|
||||||
|
|
||||||
|
numThreads {
|
||||||
|
# Ingester threads: route incoming requests, validate events/sigs (restart required)
|
||||||
|
ingester = 3
|
||||||
|
|
||||||
|
# reqWorker threads: Handle initial DB scan for events (restart required)
|
||||||
|
reqWorker = 3
|
||||||
|
|
||||||
|
# reqMonitor threads: Handle filtering of new events (restart required)
|
||||||
|
reqMonitor = 3
|
||||||
|
|
||||||
|
# negentropy threads: Handle negentropy protocol messages (restart required)
|
||||||
|
negentropy = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
negentropy {
|
||||||
|
# Support negentropy protocol messages
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Maximum records that sync will process before returning an error
|
||||||
|
maxSyncEvents = 1000000
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user