Allow multiple listeners, default to ircs
Users can now specify multiple "listen" directives in their configuration file. If -listen is specified on the CLI, it's added to the list of listeners. Listeners are now parsed as URLs. If the scheme is missing "ircs" is assumed. URLs allow to enable/disable TLS on a per-listener basis and will be used for Unix sockets too. The default listening address is changed from irc+insecure://:6667 to ircs://:6697. This avoids setting up an insecure listener opened to everybody.
This commit is contained in:
parent
754adc36fb
commit
6c1634799a
@ -13,7 +13,7 @@ A user-friendly IRC bouncer.
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
go run ./cmd/sojuctl create-user <username>
|
go run ./cmd/sojuctl create-user <username>
|
||||||
go run ./cmd/soju
|
go run ./cmd/soju -listen irc+insecure://127.0.0.1:6667
|
||||||
|
|
||||||
Then connect with username `<username>/chat.freenode.net` and join `#soju`.
|
Then connect with username `<username>/chat.freenode.net` and join `#soju`.
|
||||||
|
|
||||||
|
@ -5,15 +5,17 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.sr.ht/~emersion/soju"
|
"git.sr.ht/~emersion/soju"
|
||||||
"git.sr.ht/~emersion/soju/config"
|
"git.sr.ht/~emersion/soju/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var addr, configPath string
|
var listen, configPath string
|
||||||
var debug bool
|
var debug bool
|
||||||
flag.StringVar(&addr, "listen", "", "listening address")
|
flag.StringVar(&listen, "listen", "", "listening address")
|
||||||
flag.StringVar(&configPath, "config", "", "path to configuration file")
|
flag.StringVar(&configPath, "config", "", "path to configuration file")
|
||||||
flag.BoolVar(&debug, "debug", false, "enable debug logging")
|
flag.BoolVar(&debug, "debug", false, "enable debug logging")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -29,8 +31,11 @@ func main() {
|
|||||||
cfg = config.Defaults()
|
cfg = config.Defaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr != "" {
|
if listen != "" {
|
||||||
cfg.Addr = addr
|
cfg.Listen = append(cfg.Listen, listen)
|
||||||
|
}
|
||||||
|
if len(cfg.Listen) == 0 {
|
||||||
|
cfg.Listen = []string{":6697"}
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err := soju.OpenSQLDB(cfg.SQLDriver, cfg.SQLSource)
|
db, err := soju.OpenSQLDB(cfg.SQLDriver, cfg.SQLSource)
|
||||||
@ -38,24 +43,13 @@ func main() {
|
|||||||
log.Fatalf("failed to open database: %v", err)
|
log.Fatalf("failed to open database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ln net.Listener
|
var tlsCfg *tls.Config
|
||||||
if cfg.TLS != nil {
|
if cfg.TLS != nil {
|
||||||
cert, err := tls.LoadX509KeyPair(cfg.TLS.CertPath, cfg.TLS.KeyPath)
|
cert, err := tls.LoadX509KeyPair(cfg.TLS.CertPath, cfg.TLS.KeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to load TLS certificate and key: %v", err)
|
log.Fatalf("failed to load TLS certificate and key: %v", err)
|
||||||
}
|
}
|
||||||
|
tlsCfg = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
tlsCfg := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
||||||
ln, err = tls.Listen("tcp", cfg.Addr, tlsCfg)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to start TLS listener: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
ln, err = net.Listen("tcp", cfg.Addr)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to start listener: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
srv := soju.NewServer(db)
|
srv := soju.NewServer(db)
|
||||||
@ -64,11 +58,50 @@ func main() {
|
|||||||
srv.LogPath = cfg.LogPath
|
srv.LogPath = cfg.LogPath
|
||||||
srv.Debug = debug
|
srv.Debug = debug
|
||||||
|
|
||||||
log.Printf("server listening on %q", cfg.Addr)
|
for _, listen := range cfg.Listen {
|
||||||
go func() {
|
listenURI := listen
|
||||||
if err := srv.Run(); err != nil {
|
if !strings.Contains(listenURI, ":/") {
|
||||||
log.Fatal(err)
|
// This is a raw domain name, make it an URL with an empty scheme
|
||||||
|
listenURI = "//" + listenURI
|
||||||
}
|
}
|
||||||
}()
|
u, err := url.Parse(listenURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to parse listen URI %q: %v", listen, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "ircs", "":
|
||||||
|
if tlsCfg == nil {
|
||||||
|
log.Fatalf("failed to listen on %q: missing TLS configuration", listen)
|
||||||
|
}
|
||||||
|
host := u.Host
|
||||||
|
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||||
|
host = host + ":6697"
|
||||||
|
}
|
||||||
|
ln, err := tls.Listen("tcp", host, tlsCfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to start TLS listener on %q: %v", listen, err)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
log.Fatal(srv.Serve(ln))
|
log.Fatal(srv.Serve(ln))
|
||||||
|
}()
|
||||||
|
case "irc+insecure":
|
||||||
|
host := u.Host
|
||||||
|
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||||
|
host = host + ":6667"
|
||||||
|
}
|
||||||
|
ln, err := net.Listen("tcp", host)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
log.Fatal(srv.Serve(ln))
|
||||||
|
}()
|
||||||
|
default:
|
||||||
|
log.Fatalf("failed to listen on %q: unsupported scheme", listen)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("server listening on %q", listen)
|
||||||
|
}
|
||||||
|
log.Fatal(srv.Run())
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ type TLS struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Addr string
|
Listen []string
|
||||||
Hostname string
|
Hostname string
|
||||||
TLS *TLS
|
TLS *TLS
|
||||||
SQLDriver string
|
SQLDriver string
|
||||||
@ -28,7 +28,6 @@ func Defaults() *Server {
|
|||||||
hostname = "localhost"
|
hostname = "localhost"
|
||||||
}
|
}
|
||||||
return &Server{
|
return &Server{
|
||||||
Addr: ":6667",
|
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
SQLDriver: "sqlite3",
|
SQLDriver: "sqlite3",
|
||||||
SQLSource: "soju.db",
|
SQLSource: "soju.db",
|
||||||
@ -68,9 +67,11 @@ func Parse(r io.Reader) (*Server, error) {
|
|||||||
for _, d := range directives {
|
for _, d := range directives {
|
||||||
switch d.Name {
|
switch d.Name {
|
||||||
case "listen":
|
case "listen":
|
||||||
if err := d.parseParams(&srv.Addr); err != nil {
|
var uri string
|
||||||
|
if err := d.parseParams(&uri); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
srv.Listen = append(srv.Listen, uri)
|
||||||
case "hostname":
|
case "hostname":
|
||||||
if err := d.parseParams(&srv.Hostname); err != nil {
|
if err := d.parseParams(&srv.Hostname); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -56,15 +56,25 @@ be done by adding a "@<client>" suffix to the username.
|
|||||||
Enable debug logging (this will leak sensitive information such as
|
Enable debug logging (this will leak sensitive information such as
|
||||||
passwords).
|
passwords).
|
||||||
|
|
||||||
*-listen* <address>
|
*-listen* <uri>
|
||||||
Listening address (default: ":6667").
|
Listening URI (default: ":6697").
|
||||||
|
|
||||||
# CONFIG FILE
|
# CONFIG FILE
|
||||||
|
|
||||||
The config file has one directive per line.
|
The config file has one directive per line.
|
||||||
|
|
||||||
*listen* <address>
|
*listen* <uri>
|
||||||
Listening address (default: ":6667").
|
Listening URI (default: ":6697").
|
||||||
|
|
||||||
|
The following URIs are supported:
|
||||||
|
|
||||||
|
- _[ircs://][host][:port]_ listens with TLS over TCP (default port if
|
||||||
|
omitted: 6697)
|
||||||
|
- _irc+insecure://[host][:port]_ listens with plain-text over TCP (default
|
||||||
|
port if omitted: 6667)
|
||||||
|
|
||||||
|
If the scheme is omitted, "ircs" is assumed. If multiple *listen*
|
||||||
|
directives are specified, soju will listen on each of them.
|
||||||
|
|
||||||
*hostname* <name>
|
*hostname* <name>
|
||||||
Server hostname (default: system hostname).
|
Server hostname (default: system hostname).
|
||||||
@ -97,6 +107,7 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just
|
|||||||
Connect to a new network at _addr_. _-addr_ is mandatory.
|
Connect to a new network at _addr_. _-addr_ is mandatory.
|
||||||
|
|
||||||
_addr_ supports several connection types:
|
_addr_ supports several connection types:
|
||||||
|
|
||||||
- _[ircs://]host[:port]_ connects with TLS over TCP
|
- _[ircs://]host[:port]_ connects with TLS over TCP
|
||||||
- _irc+insecure://host[:port]_ connects with plain-text TCP
|
- _irc+insecure://host[:port]_ connects with plain-text TCP
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user