mirror of https://github.com/jlelse/GoBlog
Tor single hop mode option
This commit is contained in:
parent
e3eb3a5b4e
commit
5f52993a0c
|
@ -44,6 +44,7 @@ type configServer struct {
|
|||
TailscaleHTTPS bool `mapstructure:"tailscaleHttps"`
|
||||
Tailscale *configTailscale `mapstructure:"tailscale"`
|
||||
Tor bool `mapstructure:"tor"`
|
||||
TorSingleHop bool `mapstructure:"torSingleHop"`
|
||||
SecurityHeaders bool `mapstructure:"securityHeaders"`
|
||||
CSPDomains []string `mapstructure:"cspDomains"`
|
||||
publicHostname string
|
||||
|
|
|
@ -40,4 +40,8 @@ There's also the possibility to configure GoBlog to use Google Cloud's Text-to-S
|
|||
|
||||
On receiving a webmention, a new comment or a contact form submission, GoBlog will create a new notification. Notifications are displayed on `/notifications` and can be deleted by the user.
|
||||
|
||||
If configured, GoBlog will also send a notification using a Telegram Bot or [Ntfy.sh](https://ntfy.sh/). See the `example-config.yml` file for how to configure the notification providers.
|
||||
If configured, GoBlog will also send a notification using a Telegram Bot or [Ntfy.sh](https://ntfy.sh/). See the `example-config.yml` file for how to configure the notification providers.
|
||||
|
||||
## Tor Hidden Services
|
||||
|
||||
GoBlog can be configured to provide a Tor Hidden Service. This is useful if you want to offer your visitors a way to connect to your blog from censored networks or countries. See the `example-config.yml` file for how to enable the Tor Hidden Service. If you don't need to hide your server, you can enable the Single Hop mode.
|
|
@ -2,6 +2,14 @@
|
|||
# Until there's an official release configuration may change
|
||||
# Keep a look at the commit history
|
||||
|
||||
# Debug
|
||||
debug: true # Enable more verbose logging
|
||||
|
||||
# Pprof - Option to enable pprof profiling
|
||||
pprof:
|
||||
enabled: true # Enable pprof profiling
|
||||
address: ":6060" # Address to listen on
|
||||
|
||||
# Database
|
||||
database:
|
||||
file: data/db.sqlite # File for the SQLite database
|
||||
|
@ -25,6 +33,7 @@ server:
|
|||
- media.example.com
|
||||
# Tor
|
||||
tor: true # Publish onion service, requires Tor to be installed and available in path
|
||||
torSingleHop: true # Enable single hop mode (non-anonymous)
|
||||
# Tailscale (see https://tailscale.com)
|
||||
tailscaleHttps: true # Use an Let's Encrypt certificate from Tailscale (see https://goblog.app/s/7), requires publicHttps to be disabled
|
||||
tailscale:
|
||||
|
|
74
tor.go
74
tor.go
|
@ -29,32 +29,16 @@ func (a *goBlog) startOnionService(h http.Handler) error {
|
|||
return err
|
||||
}
|
||||
// Initialize private key
|
||||
torKeyPath := filepath.Join(torDataPath, "onion.pk")
|
||||
var torKey crypto.PrivateKey
|
||||
if _, err := os.Stat(torKeyPath); os.IsNotExist(err) {
|
||||
_, torKey, err = ed25519.GenerateKey(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x509Encoded, err := x509.MarshalPKCS8PrivateKey(torKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
|
||||
_ = os.WriteFile(torKeyPath, pemEncoded, 0600)
|
||||
} else {
|
||||
d, _ := os.ReadFile(torKeyPath)
|
||||
block, _ := pem.Decode(d)
|
||||
x509Encoded := block.Bytes
|
||||
torKey, err = x509.ParsePKCS8PrivateKey(x509Encoded)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
torKey, err := a.createTorPrivateKey(torDataPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Start tor with default config (can set start conf's DebugWriter to os.Stdout for debug logs)
|
||||
// Start tor
|
||||
log.Println("Starting and registering onion service, please wait a couple of minutes...")
|
||||
t, err := tor.Start(context.Background(), &tor.StartConf{
|
||||
TempDataDirBase: os.TempDir(),
|
||||
NoAutoSocksPort: true,
|
||||
ExtraArgs: a.torExtraArgs(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -65,9 +49,10 @@ func (a *goBlog) startOnionService(h http.Handler) error {
|
|||
defer listenCancel()
|
||||
// Create a v3 onion service to listen on any port but show as 80
|
||||
onion, err := t.Listen(listenCtx, &tor.ListenConf{
|
||||
Version3: true,
|
||||
Key: torKey,
|
||||
RemotePorts: []int{80},
|
||||
Version3: true,
|
||||
Key: torKey,
|
||||
RemotePorts: []int{80},
|
||||
NonAnonymous: a.cfg.Server.TorSingleHop,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -91,3 +76,42 @@ func (a *goBlog) startOnionService(h http.Handler) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *goBlog) createTorPrivateKey(torDataPath string) (crypto.PrivateKey, error) {
|
||||
torKeyPath := filepath.Join(torDataPath, "onion.pk")
|
||||
var torKey crypto.PrivateKey
|
||||
if _, err := os.Stat(torKeyPath); os.IsNotExist(err) {
|
||||
// Tor private key not found, create it
|
||||
_, torKey, err = ed25519.GenerateKey(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x509Encoded, err := x509.MarshalPKCS8PrivateKey(torKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
|
||||
err = os.WriteFile(torKeyPath, pemEncoded, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Tor private key found, load it
|
||||
d, _ := os.ReadFile(torKeyPath)
|
||||
block, _ := pem.Decode(d)
|
||||
x509Encoded := block.Bytes
|
||||
torKey, err = x509.ParsePKCS8PrivateKey(x509Encoded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return torKey, nil
|
||||
}
|
||||
|
||||
func (a *goBlog) torExtraArgs() []string {
|
||||
s := []string{"--SocksPort", "0"}
|
||||
if a.cfg.Server.TorSingleHop {
|
||||
s = append(s, "--HiddenServiceNonAnonymousMode", "1", "--HiddenServiceSingleHopMode", "1")
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue