Add chroot feature
This commit is contained in:
parent
5400abb1b1
commit
0324c6a93f
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -16,6 +16,7 @@
|
|||
# Dependency directories (remove the comment below to include it)
|
||||
vendor/
|
||||
|
||||
# Certificates
|
||||
# Certificates and config files
|
||||
*.crt
|
||||
*.key
|
||||
*.conf
|
||||
|
|
|
@ -39,6 +39,8 @@ It's recommended to place your certificates in the `/conf` direcory and use the
|
|||
Certfile = /conf/orion.crt
|
||||
Keyfile = /conf/orion.key
|
||||
|
||||
Note: Use the `chroot` setting in containers for additional security.
|
||||
|
||||
## Credits
|
||||
|
||||
* This project was inspired by the [titan2](https://gitlab.com/lostleonardo/titan2) minimalistic Gemini server written by lostleonardo.
|
||||
|
|
|
@ -13,6 +13,7 @@ type Config struct {
|
|||
Keyfile string // Key file
|
||||
BindAddr string // Optional binding address
|
||||
ContentDir string // Gemini content directory to serve
|
||||
Chroot string // chroot directory, if configured
|
||||
}
|
||||
|
||||
func (cf *Config) SetDefaults() {
|
||||
|
@ -53,6 +54,8 @@ func (cf *Config) LoadConfigFile(filename string) error {
|
|||
cf.BindAddr = value
|
||||
} else if name == "contentdir" {
|
||||
cf.ContentDir = value
|
||||
} else if name == "chroot" {
|
||||
cf.Chroot = value
|
||||
} else {
|
||||
return fmt.Errorf("Unknown setting in line %d", lineCount)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
@ -40,6 +41,17 @@ func tryLoadConfig(filename string) {
|
|||
}
|
||||
}
|
||||
|
||||
func chroot(dir string) error {
|
||||
runtime.LockOSThread()
|
||||
if err := syscall.Chroot(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Chdir("/"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
config.SetDefaults()
|
||||
|
||||
|
@ -57,6 +69,29 @@ func main() {
|
|||
tryLoadConfig("./orion.conf")
|
||||
}
|
||||
|
||||
// Load keys before chroot
|
||||
if !FileExists(config.Keyfile) {
|
||||
fmt.Fprintf(os.Stderr, "Server key file not found: %s\n", config.Keyfile)
|
||||
os.Exit(1)
|
||||
}
|
||||
if !FileExists(config.CertFile) {
|
||||
fmt.Fprintf(os.Stderr, "Certificate file not found: %s\n", config.CertFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
cert, err := tls.LoadX509KeyPair(config.CertFile, config.Keyfile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "certificate error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Chroot, if configured to do so
|
||||
if config.Chroot != "" {
|
||||
if err := chroot(config.Chroot); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "chroot failed: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Make the content dir absolute
|
||||
if !strings.HasPrefix(config.ContentDir, "/") {
|
||||
workDir, err := os.Getwd()
|
||||
|
@ -71,16 +106,6 @@ func main() {
|
|||
config.ContentDir += "/"
|
||||
}
|
||||
|
||||
// Check settings
|
||||
if !FileExists(config.Keyfile) {
|
||||
fmt.Fprintf(os.Stderr, "Server key file not found: %s\n", config.Keyfile)
|
||||
os.Exit(1)
|
||||
}
|
||||
if !FileExists(config.CertFile) {
|
||||
fmt.Fprintf(os.Stderr, "Certificate file not found: %s\n", config.CertFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Content warnings should point user at wrong configuration early in the program
|
||||
if !DirectoryExists(config.ContentDir) {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: Content directory does not exist: %s\n", config.ContentDir)
|
||||
|
@ -91,11 +116,6 @@ func main() {
|
|||
}
|
||||
|
||||
// Setup gemini server
|
||||
cert, err := tls.LoadX509KeyPair(config.CertFile, config.Keyfile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "certificate error: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
server, err := CreateGeminiServer(config.Hostname, config.BindAddr, cert)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "server error: %s\n", err)
|
||||
|
|
13
orion.conf
13
orion.conf
|
@ -2,14 +2,19 @@
|
|||
## Please modify this file to your needs
|
||||
## lines starting with a '#' are comments and will be ignored
|
||||
|
||||
# Server hostname and listen address
|
||||
# Bind ':1965' will bind to any IP address and port 1965
|
||||
## Server hostname and listen address
|
||||
## Bind ':1965' will bind to any IP address and port 1965
|
||||
Hostname = localhost
|
||||
Bind = :1965
|
||||
|
||||
# TLS certificate
|
||||
## TLS certificate
|
||||
## Note: Those files will be loaded before chroot!
|
||||
Certfile = orion.crt
|
||||
Keyfile = orion.key
|
||||
|
||||
# Content directory
|
||||
## Content directory
|
||||
ContentDir = ./gemini/
|
||||
|
||||
## Chroot into this directory (uncomment to enable)
|
||||
## Note: If enabled, the ContentDir needs to be adapted accordingly
|
||||
# chroot = /srv/gemini/
|
||||
|
|
Loading…
Reference in a new issue