Files
tchivert 0f666c102f
build / build (push) Successful in 7m39s
ipv6 fixes
2024-04-06 23:20:26 +02:00

183 lines
4.8 KiB
Go

package main
import (
"crypto/rand"
"database/sql"
"flag"
"fmt"
"net"
"os"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
"github.com/oschwald/geoip2-golang"
)
var (
tarpit = flag.Bool("tarpit", false, "Tarpit connections")
db = flag.String("db", "./logs.db", "Path to SQLite database")
geoip = flag.String("geoip", "", "Path to GeoIP databases")
port = flag.String("port", "2222", "Port to listen on")
mysql_user = flag.String("mysql_user", "", "MySQL username")
mysql_pass = flag.String("mysql_pass", "", "MySQL password")
mysql_host = flag.String("mysql_host", "localhost", "MySQL host")
mysql_port = flag.String("mysql_port", "3306", "MySQL port")
mysql_db = flag.String("mysql_db", "sshtarpit", "MySQL database")
)
const (
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
delay = 1
)
func main() {
flag.Parse()
fmt.Println("Listening on port", *port)
ln, err := net.Listen("tcp", ":"+*port)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
header := []byte("SSH-2.0-OpenSSH_9.1p1 Debian-1\r")
src := conn.RemoteAddr().String()
ip := src[:len(src)-6]
if strings.Contains(ip, "[") {
ip = ip[1 : len(ip)-1]
}
if *geoip != "" {
registerGeoip(ip)
} else {
registerConnection(ip)
}
if !*tarpit {
conn.Write(header)
time.Sleep(time.Duration(2) * time.Second)
} else {
for {
b := make([]byte, 1)
_, err := rand.Read(b)
if err != nil {
fmt.Println(err)
return
}
conn.Write([]byte{charset[int(b[0])%len(charset)]})
time.Sleep(time.Duration(delay) * time.Second)
}
}
}
func registerGeoip(ip string) {
location, err := geoip2.Open(*geoip + "/GeoLite2-City.mmdb")
if err != nil {
fmt.Println(err)
registerConnection(ip)
return
}
defer location.Close()
city, err := location.City(net.ParseIP(ip))
if err != nil {
fmt.Println(err)
registerConnection(ip)
return
}
latitude, longitude := city.Location.Latitude, city.Location.Longitude
if latitude == 0 && longitude == 0 {
registerConnection(ip)
return
}
ispdb, err := geoip2.Open(*geoip + "/GeoLite2-ASN.mmdb")
if err != nil {
fmt.Println(err)
registerConnection(ip)
return
}
defer ispdb.Close()
isp, err := ispdb.ASN(net.ParseIP(ip))
if err != nil {
fmt.Println(err)
registerConnection(ip)
return
}
if *mysql_user != "" {
_, err = mysqlInsert(ip, city.Country.Names["en"], city.City.Names["en"], latitude, longitude, isp.AutonomousSystemOrganization)
} else {
_, err = sqliteInsert(ip, city.Country.Names["en"], city.City.Names["en"], latitude, longitude, isp.AutonomousSystemOrganization)
}
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Connection from", ip, "(", city.Country.Names["en"], city.City.Names["en"], isp.AutonomousSystemOrganization, ")")
}
func registerConnection(ip string) {
if *mysql_user != "" {
_, err := mysqlInsert(ip, "", "", 0, 0, "")
if err != nil {
fmt.Println(err)
return
}
} else {
_, err := sqliteInsert(ip, "", "", 0, 0, "")
if err != nil {
fmt.Println(err)
return
}
}
fmt.Println("Connection from", ip)
}
func mysqlInsert(ip, country, city string, latitude, longitude float64, isp string) (int64, error) {
sqldb, err := sql.Open("mysql", *mysql_user+":"+*mysql_pass+"@tcp("+*mysql_host+":"+*mysql_port+")/"+*mysql_db)
if err != nil {
fmt.Println(err)
return 0, err
}
defer sqldb.Close()
_, err = sqldb.Exec("CREATE TABLE IF NOT EXISTS connections (ip TEXT, country TEXT, city TEXT, latitude REAL, longitude REAL, isp TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")
if err != nil {
fmt.Println(err)
return 0, err
}
res, err := sqldb.Exec("INSERT INTO connections (ip, country, city, latitude, longitude, isp, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)", ip, country, city, latitude, longitude, isp, time.Now().Format("2006-01-02 15:04:05"))
if err != nil {
fmt.Println(err)
return 0, err
}
return res.LastInsertId()
}
func sqliteInsert(ip, country, city string, latitude, longitude float64, isp string) (int64, error) {
sqldb, err := sql.Open("sqlite3", *db)
if err != nil {
fmt.Println(err)
return 0, err
}
defer sqldb.Close()
_, err = sqldb.Exec("CREATE TABLE IF NOT EXISTS connections (ip TEXT, country TEXT, city TEXT, latitude REAL, longitude REAL, isp TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")
if err != nil {
fmt.Println(err)
return 0, err
}
res, err := sqldb.Exec("INSERT INTO connections (ip, country, city, latitude, longitude, isp, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)", ip, country, city, latitude, longitude, isp, time.Now().Format("2006-01-02 15:04:05"))
if err != nil {
fmt.Println(err)
return 0, err
}
return res.RowsAffected()
}