sshlog/main.go

151 lines
3.2 KiB
Go
Raw Permalink Normal View History

2021-06-01 23:05:41 +02:00
package main
import (
2021-06-01 23:27:41 +02:00
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
2021-06-01 23:05:41 +02:00
"fmt"
"log"
"net"
"os"
2021-06-02 23:37:22 +02:00
"sync"
"time"
2021-06-01 23:05:41 +02:00
flags "github.com/spf13/pflag"
"golang.org/x/crypto/ssh"
)
2021-06-03 00:12:34 +02:00
var (
port string
isHelp bool
keyPath string
onlyIPv4 bool
isJson bool
2021-06-03 00:12:34 +02:00
)
func init() {
flags.StringVarP(&port, "port", "p", "22", "Port to listen for incoming connections.")
2021-06-01 23:27:41 +02:00
flags.StringVarP(&keyPath, "key", "k", "", "Path to the host key for the ssh server.\nIf absent it will automatically generate a new one for each run.")
2021-06-01 23:05:41 +02:00
flags.BoolVarP(&isHelp, "help", "h", false, "Prints this help message and exits.")
2021-06-03 00:12:34 +02:00
flags.BoolVarP(&onlyIPv4, "onlyIPv4", "4", false, "Only listens on IPv4.")
flags.BoolVar(&isJson, "json", false, "Log in JSON instead of plain text.")
2021-06-01 23:05:41 +02:00
flags.Parse()
2021-06-03 00:12:34 +02:00
}
func main() {
2021-06-01 23:05:41 +02:00
if isHelp {
printHelp()
os.Exit(0)
}
privateKey := getKey(keyPath)
hostKey, err := ssh.ParsePrivateKey(privateKey)
if err != nil {
log.Fatal("Failed to parse private key")
}
2021-06-01 23:27:41 +02:00
serverConfig := ssh.ServerConfig{PasswordCallback: printConnectionData}
serverConfig.AddHostKey(hostKey)
log.Printf("Starting ssh logger on port %s...\n", port)
2021-06-20 16:21:55 +02:00
ipv4Listener, err := net.Listen("tcp", "0.0.0.0:"+port)
2021-06-01 23:05:41 +02:00
if err != nil {
panic(err)
}
2021-06-02 23:37:22 +02:00
defer ipv4Listener.Close()
2021-06-01 23:05:41 +02:00
2021-06-02 23:37:22 +02:00
wg := new(sync.WaitGroup)
wg.Add(1)
go startAccepting(ipv4Listener, serverConfig)
2021-06-03 00:12:34 +02:00
if !onlyIPv4 {
ipv6Listener, err := net.Listen("tcp", "[::1]:"+port)
if err != nil {
panic(err)
}
defer ipv6Listener.Close()
wg.Add(1)
go startAccepting(ipv6Listener, serverConfig)
2021-06-03 00:12:34 +02:00
}
2021-06-02 23:37:22 +02:00
wg.Wait() // Waits until it gets terminated
}
func startAccepting(listener net.Listener, serverConfig ssh.ServerConfig) {
2021-06-01 23:05:41 +02:00
for {
con, err := listener.Accept()
if err != nil {
log.Println(err)
2021-06-01 23:05:41 +02:00
}
go connectionHandler(con, serverConfig)
2021-06-01 23:27:41 +02:00
}
}
func getKey(path string) []byte {
if path != "" {
privateBytes, err := os.ReadFile(path)
2021-06-01 23:27:41 +02:00
if err != nil {
log.Fatalf("Failed to load private key: %s", path)
2021-06-01 23:27:41 +02:00
}
return privateBytes
}
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
2021-06-01 23:27:41 +02:00
if err != nil {
log.Fatalf("Cannot generate RSA key\n")
2021-06-01 23:05:41 +02:00
}
2021-06-01 23:27:41 +02:00
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPem := pem.EncodeToMemory(
2021-06-01 23:27:41 +02:00
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
2021-06-01 23:27:41 +02:00
},
)
return privateKeyPem
2021-06-01 23:05:41 +02:00
}
func connectionHandler(con net.Conn, serverConfig ssh.ServerConfig) {
_, _, _, err := ssh.NewServerConn(con, &serverConfig)
2021-06-01 23:05:41 +02:00
if err != nil {
return
}
}
func printConnectionData(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
responseErr := fmt.Errorf("password rejected for %s", conn.User())
ip, _, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil {
fmt.Println(err)
return nil, responseErr
}
if isJson {
fmt.Printf(
"{\"date\": \"%s\", \"src\": \"%s\", \"username\": \"%s\", \"password\": \"%s\"}\n",
time.Now().Format(time.RFC3339),
ip,
conn.User(),
string(password),
)
} else {
log.Printf("SRC=%s USERNAME=%s PASSWORD=%s\n", ip, conn.User(), string(password))
}
return nil, responseErr
}
2021-06-01 23:05:41 +02:00
func printHelp() {
2021-06-03 00:19:56 +02:00
fmt.Println(`A small tool to log IPs, usernames and passwords from incoming ssh-auth requests.
2021-06-01 23:27:41 +02:00
2021-06-01 23:05:41 +02:00
USAGE:
sshlog [FLAGS]
FLAGS:`)
flags.PrintDefaults()
}