WebSockets provide full-duplex communication channels over a single TCP connection, commonly used in applications such as online gaming, stock trading platforms, and collaborative editing. However, when securing these connections over the internet, it is essential to use Transport Layer Security (TLS) to prevent eavesdropping and protect data integrity. In this article, we will explore how to create secure WebSocket connections in a Go application using the github.com/gorilla/websocket package with TLS.
Setting up a Basic WebSocket Server
Before we delve into securing our WebSocket, let's start with setting up a basic WebSocket server using the Gorilla WebSocket library. To begin, ensure that you have Go installed and that your environment is set up correctly. Then, initialize a new Go module:
go mod init example.com/securewsInstall the Gorilla WebSocket package:
go get -u github.com/gorilla/websocketNow, let's create the basic WebSocket server:
package main
import (
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func handleConnections(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a websocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatalf("Error upgrading to websocket: %v", err)
}
defer ws.Close()
for {
// Read a message from websocket
messageType, msg, err := ws.ReadMessage()
if err != nil {
log.Printf("Error reading message: %v", err)
break
}
// Echo the message back
err = ws.WriteMessage(messageType, msg)
if err != nil {
log.Printf("Error writing message: %v", err)
break
}
}
}
func main() {
http.HandleFunc("/ws", handleConnections)
log.Println("Server started on :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("ListenAndServe: %v", err)
}
}Adding TLS Support
To secure the WebSocket server using TLS, you need to create or obtain an SSL certificate and a private key. For development purposes, you can generate a self-signed certificate:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodesOnce you have the certificate and key, you can modify the server code to enable TLS:
func main() {
http.HandleFunc("/ws", handleConnections)
log.Println("Server started on :8443")
err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil)
if err != nil {
log.Fatalf("ListenAndServeTLS: %v", err)
}
}With this setup, your WebSocket server now communicates over a secure TLS connection.
Connecting from the Client Side
To connect to this secure WebSocket server from a client application, you'll typically use the wss:// scheme (WebSocket Secure). Here’s an example of how you might do it using JavaScript in a web browser:
const socket = new WebSocket('wss://localhost:8443/ws');
socket.addEventListener('open', function (event) {
console.log('Connected to WebSocket Server');
socket.send('Hello Server!');
});
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});Note that since we are using a self-signed certificate, you might need to handle SSL warnings or exceptions in the browser settings or application configuration.
Conclusion
In this article, we covered the process of setting up a secure WebSocket server using Go and Gorilla WebSockets with TLS encryption. Secure WebSocket connections are crucial for protecting data and maintaining user privacy. With TLS in place, you can ensure that your WebSocket communications are both secure and reliable.