From bc3cd19b24b371b0786fd108af8c7ae28a39cf49 Mon Sep 17 00:00:00 2001 From: dalbodeule <11470513+dalbodeule@users.noreply.github.com> Date: Tue, 14 Oct 2025 21:21:12 +0900 Subject: [PATCH] Dockerfile and some add/fix config --- Dockerfile | 35 +++++++++++++++++++++++++++++++++++ inc.env | 5 +++-- main.go | 30 +++++++++++++++++++----------- utils/config.go | 9 ++++----- utils/geoip.go | 3 --- utils/hostkey.go | 20 +++++++++++--------- 6 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..71f09db --- /dev/null +++ b/Dockerfile @@ -0,0 +1,35 @@ +# Stage 1: Build the Go application +FROM golang:1.25-alpine AS builder + +WORKDIR /app + +# Copy go.mod and go.sum first to leverage Docker cache +COPY go.mod go.sum ./ +RUN go mod download + +# Copy the rest of the application source code +COPY . . + +# Build the Go application +# CGO_ENABLED=0 disables CGO, creating a statically linked binary +# -o /app/main specifies the output path and name of the executable +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /app/main . + +# Stage 2: Create a minimal runtime image +FROM alpine:latest + +# Install ca-certificates for HTTPS support if needed +RUN apk --no-cache add ca-certificates + +WORKDIR /root/ + +# Copy the built executable from the builder stage +COPY --from=builder /app/main . + +# Expose the port your application listens on (e.g., 2222) +EXPOSE 2222 +ENV PORT=2222 +ENV ROOT_PATH="/app/data" + +# Command to run the application when the container starts +CMD ["./main"] \ No newline at end of file diff --git a/inc.env b/inc.env index 4b41664..4dd5187 100644 --- a/inc.env +++ b/inc.env @@ -1,3 +1,4 @@ PORT=2222 -GEOIP_DB=./GeoLite2-City.mmdb -DB_DSN="postgrtesql://postgres:password@localhost/postgres" \ No newline at end of file +GEOIP_DB=GeoLite2-City.mmdb +DB_DSN="postgrtesql://postgres:password@localhost/postgres" +ROOT_PATH="./" \ No newline at end of file diff --git a/main.go b/main.go index 931852e..e2b751d 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "net" "slices" "strings" @@ -24,7 +25,12 @@ func sessionHandler(s ssh.Session, geoip *geoip2.Reader, pgDb *bun.DB) { return } - remote := s.RemoteAddr().String() + addr := s.RemoteAddr().String() + host, _, err := net.SplitHostPort(addr) + if err != nil { + host = addr + } + remote := strings.Trim(host, "[]") username := s.User() geoStatus := utils.GetIPInfo(remote, geoip) @@ -43,12 +49,14 @@ func sessionHandler(s ssh.Session, geoip *geoip2.Reader, pgDb *bun.DB) { _ = s.Close() } - if geoStatus.Country == "ZZ" && !(strings.HasPrefix(remote, "127") || strings.HasPrefix(remote, "[::1]")) { - log.Printf("[sshchat] unknown country blacklisted. %s", username) - _, _ = fmt.Fprintf(s, "[system] Unknown country is blacklisted. %s\n", geoStatus.Country) - _ = s.Close() - } else { - log.Printf("[sshchat] %s is localhost whitelisted.", username) + if geoStatus.Country == "ZZ" { + if strings.HasPrefix(remote, "127") || strings.HasPrefix(remote, "::1") { + log.Printf("[sshchat] %s is localhost whitelisted.", username) + } else { + log.Printf("[sshchat] unknown country blacklisted. %s", username) + _, _ = fmt.Fprintf(s, "[system] Unknown country is blacklisted. %s\n", geoStatus.Country) + _ = s.Close() + } } client := utils.NewClient(s, ptyReq.Window.Height, ptyReq.Window.Width, username, remote) @@ -62,7 +70,7 @@ func sessionHandler(s ssh.Session, geoip *geoip2.Reader, pgDb *bun.DB) { } func main() { - geoip, err := utils.GetDB(config.Geoip) + geoip, err := utils.GetDB(config.RootPath + "/" + config.Geoip) if err != nil { log.Fatalf("Geoip db is error: %v", err) } @@ -74,15 +82,15 @@ func main() { port := config.Port - keys, err := utils.CheckHostKey() + keys, err := utils.CheckHostKey(config.RootPath) if err != nil { log.Print("Failed to check SSH keys: generate one.\n", err) - err = utils.GenerateHostKey() + err = utils.GenerateHostKey(config.RootPath) if err != nil { log.Fatal(err) } - keys, err = utils.CheckHostKey() + keys, err = utils.CheckHostKey(config.RootPath) if err != nil { log.Fatal(err) } diff --git a/utils/config.go b/utils/config.go index 47b2e8b..444782a 100644 --- a/utils/config.go +++ b/utils/config.go @@ -1,7 +1,6 @@ package utils import ( - "log" "os" "strings" @@ -13,23 +12,23 @@ type Config struct { Geoip string CountryBlacklist []string PgDsn string + RootPath string } func GetConfig() *Config { - err := godotenv.Load() - if err != nil { - log.Fatal("Error loading .env file") - } + _ = godotenv.Load() port := os.Getenv("PORT") geoipDbfile := os.Getenv("GEOIP_DB") countryBlacklist := os.Getenv("COUNTRY_BLACKLIST") pgDsn := os.Getenv("DB_DSN") + rootPath := os.Getenv("ROOT_PATH") return &Config{ Port: port, Geoip: geoipDbfile, CountryBlacklist: strings.Split(countryBlacklist, ","), PgDsn: pgDsn, + RootPath: rootPath, } } diff --git a/utils/geoip.go b/utils/geoip.go index 94c4c46..e56eecb 100644 --- a/utils/geoip.go +++ b/utils/geoip.go @@ -30,10 +30,7 @@ func GetIPInfo(ip string, db *geoip2.Reader) *IpInfo { country := func(ip net.IP) string { country, _ := db.Country(parsedIp) - println(country.Country.IsoCode) - if country != nil && country.Country.IsoCode != "" { - println(country.Country.IsoCode) return country.Country.IsoCode } else { return "ZZ" diff --git a/utils/hostkey.go b/utils/hostkey.go index 5a1a40f..e66bda4 100644 --- a/utils/hostkey.go +++ b/utils/hostkey.go @@ -15,8 +15,8 @@ import ( // GenerateHostKey는 'keys' 디렉토리를 생성하고, RSA, ECDSA, Ed25519 호스트 개인 키를 생성하여 저장합니다. // 개인 키는 OpenSSH 형식으로 암호화되어 저장됩니다. -func GenerateHostKey() error { - const keyDir = "./keys" +func GenerateHostKey(rootPath string) error { + keyDir := rootPath + "/keys" // 1. 키 디렉토리 생성 if err := os.MkdirAll(keyDir, 0700); err != nil { @@ -103,25 +103,27 @@ func generateAndSaveKey(path string, keyType string) error { return nil } -func CheckHostKey() ([]ssh.Signer, error) { - keyFiles := []string{"./keys/id_rsa", "./keys/id_ecdsa", "./keys/id_ed25519"} +func CheckHostKey(rootPath string) ([]ssh.Signer, error) { + keyFiles := []string{"keys/id_rsa", "keys/id_ecdsa", "keys/id_ed25519"} for _, keyFile := range keyFiles { - if _, err := os.Stat(keyFile); os.IsNotExist(err) { - return nil, fmt.Errorf("key file %s does not exist", keyFile) + tmp := rootPath + "/" + keyFile + if _, err := os.Stat(tmp); os.IsNotExist(err) { + return nil, fmt.Errorf("key file %s does not exist", tmp) } } var keys = make([]ssh.Signer, 0) for _, keyFile := range keyFiles { - keyBytes, err := os.ReadFile(keyFile) + tmp := rootPath + "/" + keyFile + keyBytes, err := os.ReadFile(tmp) if err != nil { - return nil, fmt.Errorf("failed to read key file %s: %v", keyFile, err) + return nil, fmt.Errorf("failed to read key file %s: %v", tmp, err) } signer, err := ssh.ParsePrivateKey(keyBytes) if err != nil { - return nil, fmt.Errorf("failed to parse private key %s: %v", keyFile, err) + return nil, fmt.Errorf("failed to parse private key %s: %v", tmp, err) } keys = append(keys, signer)