You've already forked ssh-tarpit
183 lines
4.8 KiB
Go
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()
|
|
}
|