Skip to content

Commit

Permalink
Added basic TLS support
Browse files Browse the repository at this point in the history
Using -key and -cert CLI optins.

Signed-off-by: Andrea Barberio <[email protected]>
  • Loading branch information
insomniacslk committed May 6, 2020
1 parent e38b1e9 commit 59beccd
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 14 deletions.
47 changes: 40 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,28 @@ You can also [run it with Docker](#run-it-with-docker).

## Encryption

`irc-slack` provides no encryption between your IRC client and `irc-slack`, but
the communication between `irc-slack` and the Slack servers is encrypted.
`irc-slack` by default does not use encryption when communicating with your IRC
client (but the communication between `irc-slack` and the Slack servers is
encrypted).
If you want to use TLS, you can use the `-key` and `-cert` command line
parameters, and point them to a TLS certificate that you own.
This is useful if you plan to connect to to `irc-slack` over the internet.

For example, you can generate a valid certificate with LetsEncrypt (adjust the relevant
fields of course):
```
sudo certbot certonly \
-n \
-d your.domain.example.com \
--test-cert \
--standalone \
-m [email protected] \
--agree-tos
```

It is not recommended to connect to `irc-slack` over the internet (i.e. run it on
your loopback interface, as long as you trust your machines' users). If you need
to do so, put a TLS proxy in front of it.
Then your key and certificate will be generated under
`/etc/letsencrypt/live/your.domain.example.com`
with the names `privkey.pem` and `cert.pem` respectively.

## Authentication

Expand All @@ -47,6 +63,8 @@ three possible methods:
* legacy tokens (soon to be deprecated)

These options are discussed in more detail below.
Then just add `-key <path/to/privkey.pem> -cert <path/to/cert.pem>` to enable
TLS on `irc-slack`, and enable TLS on your IRC client.


### User tokens with auth cookie
Expand Down Expand Up @@ -130,18 +148,33 @@ docker build -f Dockerfile . -t insomniacslk/irc-slack

### Connecting with irssi
```
/network add SlackYourTeamName
/server add -auto -network SlackYourTeamName localhost 6666 xoxp-<your-slack-token>
/network add yourteam.slack.com
/server add -auto -network yourteam.slack.com localhost 6666 xoxp-<your-slack-token>
/connect yourteam.slack.com
```

Remember to add `-tls` to the `/connect` command if you're running `irc-slack`
with TLS.
Also remember to replace `localhost` with the name of the host you're connecting to,
if different.

### Connecting with WeeChat

```
/server add yourteam.slack.com localhost/6666
/set irc.server.yourteam.slack.com.password xoxp-<your-slack-token>
/connect yourteam.slack.com
```

To enable TLS, also run the following before the `/connect` command:
```
/set irc.server.yourteam.slack.com.ssl on
/set irc.server.yourteam.slack.com.ssl_verify on
```

Also remember to replace `localhost` with the name of the host you're connecting to,
if different.

## Gateway usage

There are a few options that you can pass to the server, e.g. to change the listener port, or the server name:
Expand Down
2 changes: 1 addition & 1 deletion irc_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type SlackPostMessage struct {

// IrcContext holds the client context information
type IrcContext struct {
Conn *net.TCPConn
Conn net.Conn
User *slack.User
// TODO make RealName a function
RealName string
Expand Down
19 changes: 19 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"crypto/tls"
"flag"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -32,6 +33,8 @@ var (
logLevel = flag.String("L", "info", fmt.Sprintf("Log level. One of %v", getLogLevels()))
flagSlackDebug = flag.Bool("D", false, "Enable debug logging of the Slack API")
flagPagination = flag.Int("P", 0, "Pagination value for API calls. If 0 or unspecified, use the recommended default (currently 200). Larger values can help on large Slack teams")
flagKey = flag.String("key", "", "TLS key for HTTPS server. Requires -cert")
flagCert = flag.String("cert", "", "TLS certificate for HTTPS server. Requires -key")
)

var log = logger.GetLogger("main")
Expand Down Expand Up @@ -81,6 +84,21 @@ func main() {
log.Fatalf("Missing or invalid download directory: %s", *fileDownloadLocation)
}
}
doTLS := false
if *flagKey != "" && *flagCert != "" {
doTLS = true
}
var tlsConfig *tls.Config
if doTLS {
if *flagKey == "" || *flagCert == "" {
log.Fatalf("-key and -cert must be specified together")
}
cert, err := tls.LoadX509KeyPair(*flagCert, *flagKey)
if err != nil {
log.Fatalf("Failed to load TLS key/cert: %v", err)
}
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}}
}
server := Server{
LocalAddr: &localAddr,
Name: sName,
Expand All @@ -89,6 +107,7 @@ func main() {
FileProxyPrefix: *fileProxyPrefix,
SlackDebug: *flagSlackDebug,
Pagination: *flagPagination,
TLSConfig: tlsConfig,
}
if err := server.Start(); err != nil {
log.Fatal(err)
Expand Down
18 changes: 12 additions & 6 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bufio"
"crypto/tls"
"fmt"
"io"
"net"
Expand All @@ -14,35 +15,40 @@ import (
type Server struct {
Name string
LocalAddr net.Addr
Listener *net.TCPListener
Listener net.Listener
SlackAPIKey string
SlackDebug bool
ChunkSize int
FileDownloadLocation string
FileProxyPrefix string
Pagination int
TLSConfig *tls.Config
}

// Start runs the IRC server
func (s Server) Start() error {
listener, err := net.Listen("tcp", s.LocalAddr.String())
var err error
if s.TLSConfig != nil {
s.Listener, err = tls.Listen("tcp", s.LocalAddr.String(), s.TLSConfig)
} else {
s.Listener, err = net.Listen("tcp", s.LocalAddr.String())
}
if err != nil {
return err
}
s.Listener = listener.(*net.TCPListener)
defer s.Listener.Close()
log.Infof("Listening on %v", s.LocalAddr)
for {
conn, err := s.Listener.Accept()
if err != nil {
return fmt.Errorf("Error accepting: %v", err)
}
go s.HandleRequest(conn.(*net.TCPConn))
go s.HandleRequest(conn)
}
}

// HandleRequest handle IRC client connections
func (s Server) HandleRequest(conn *net.TCPConn) {
func (s Server) HandleRequest(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
Expand All @@ -62,7 +68,7 @@ func (s Server) HandleRequest(conn *net.TCPConn) {
}

// HandleMsg handles raw IRC messages
func (s *Server) HandleMsg(conn *net.TCPConn, msg string) {
func (s *Server) HandleMsg(conn net.Conn, msg string) {
if strings.HasPrefix(msg, "PASS ") {
log.Debugf("%v: PASS ***** (redacted for privacy)", conn.RemoteAddr())
} else {
Expand Down

0 comments on commit 59beccd

Please sign in to comment.