Add native SSL/TLS listener support from @enmand for our new config

This commit is contained in:
Daniel Oaks 2016-04-13 20:45:09 +10:00
parent 8dc2732137
commit c3288823af
5 changed files with 57 additions and 9 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/ircd.*
/ssl.*

View File

@ -11,14 +11,13 @@ Oragono is a very early, extremely experimental fork of the [Ergonomadic](https:
* channels that [persist][go-sqlite] between restarts (+P)
* messages are queued in the same order to all connected clients
# What about SSL/TLS support?
# What about SSL/TLS?
Go has a not-yet-verified-as-safe TLS 1.2 implementation. Sadly, many popular
IRC clients will negotiate nothing newer than SSLv2. If you want to use SSL to
protect traffic, I recommend using
There is inbuilt TLS support using the Go TLS implementation. However,
[stunnel](https://www.stunnel.org/index.html) version 4.56 with haproxy's
[PROXY protocol][proxy-proto]. This will allow the server to get the client's
original addresses for hostname lookups.
[PROXY protocol](http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt)
may also be used. This will allow the server to get the client's original
addresses for hostname lookups.
# Installation

View File

@ -1,6 +1,7 @@
package irc
import (
"crypto/tls"
"errors"
"io/ioutil"
"log"
@ -12,6 +13,24 @@ type PassConfig struct {
Password string
}
// SSLListenConfig defines configuration options for listening on SSL
type SSLListenConfig struct {
Cert string
Key string
}
// Certificate returns the SSL certificate assicated with this SSLListenConfig
func (conf *SSLListenConfig) Config() (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(conf.Cert, conf.Key)
if err != nil {
return nil, errors.New("ssl cert+key: invalid pair")
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
}, err
}
func (conf *PassConfig) PasswordBytes() []byte {
bytes, err := DecodePassword(conf.Password)
if err != nil {
@ -35,6 +54,8 @@ type Config struct {
MOTD string
}
SSLListener map[string]*SSLListenConfig
Operator map[string]*PassConfig
Theater map[string]*PassConfig
@ -60,6 +81,18 @@ func (conf *Config) Theaters() map[Name][]byte {
return theaters
}
func (conf *Config) SSLListeners() map[Name]*tls.Config {
sslListeners := make(map[Name]*tls.Config)
for s, sslListenersConf := range conf.SSLListener {
config, err := sslListenersConf.Config()
if err != nil {
log.Fatal(err)
}
sslListeners[NewName(s)] = config
}
return sslListeners
}
func LoadConfig(filename string) (config *Config, err error) {
data, err := ioutil.ReadFile(filename)
if err != nil {

View File

@ -2,6 +2,7 @@ package irc
import (
"bufio"
"crypto/tls"
"database/sql"
"fmt"
"log"
@ -88,7 +89,7 @@ func NewServer(config *Config) *Server {
server.loadChannels()
for _, addr := range config.Server.Listen {
server.listen(addr)
server.listen(addr, config.SSLListeners())
}
if config.Server.Wslisten != "" {
@ -223,13 +224,18 @@ func (server *Server) Run() {
// listen goroutine
//
func (s *Server) listen(addr string) {
func (s *Server) listen(addr string, ssl map[Name]*tls.Config) {
config, listenSSL := ssl[NewName(addr)]
listener, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(s, "listen error: ", err)
}
Log.info.Printf("%s listening on %s", s, addr)
if listenSSL {
listener = tls.NewListener(listener, config)
}
Log.info.Printf("%s listening on %s. ssl: %t", s, addr, listenSSL)
go func() {
for {
@ -250,6 +256,7 @@ func (s *Server) listen(addr string) {
//
func (s *Server) wslisten(addr string) {
//TODO(dan): open a https websocket here if ssl/tls details are setup in the config for the wslistener
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
Log.error.Printf("%s method not allowed", s)

View File

@ -18,6 +18,7 @@ server:
- ":6667"
- "127.0.0.1:6668"
- "[::1]:6668"
- ":6697" # ssl port
# websocket listening port
wslisten: ":8080"
@ -33,6 +34,13 @@ server:
# if you change the motd, you should move it to ircd.motd
motd: oragono.motd
# ssl listeners
ssllistener:
# listener on ":6697"
":6697":
key: ssl.key
cert: ssl.crt
# ircd operators
operator:
# operator named 'dan'