This commit is contained in:
cangui 2025-08-16 21:22:08 +02:00
parent 5b35c1d12e
commit 0ec0f33af6

62
main.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"canguidev/shelfy/internal/db" "canguidev/shelfy/internal/db"
"canguidev/shelfy/internal/routes" "canguidev/shelfy/internal/routes"
"canguidev/shelfy/internal/utils" "canguidev/shelfy/internal/utils"
@ -22,22 +23,48 @@ import (
type mainDriver struct{} type mainDriver struct{}
// tcpKeepAliveListener est un wrapper générique qui active le keep-alive
// sur chaque connexion acceptée par un net.Listener.
type tcpKeepAliveListener struct{ net.Listener }
func (l tcpKeepAliveListener) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
if err != nil {
return nil, err
}
if tc, ok := c.(*net.TCPConn); ok {
_ = tc.SetKeepAlive(true)
_ = tc.SetKeepAlivePeriod(30 * time.Second)
}
return c, nil
}
// clientDriver : wrapper sur afero.Fs
type clientDriver struct { type clientDriver struct {
fs afero.Fs fs afero.Fs
} }
func (d *mainDriver) GetSettings() (*ftpserver.Settings, error) { func (d *mainDriver) GetSettings() (*ftpserver.Settings, error) {
// Listener principal (port 2121) avec TCP keep-alive activé
lc := net.ListenConfig{
KeepAlive: 30 * time.Second, // garde la connexion de contrôle vivante côté NAT/pare-feu
}
ln, err := lc.Listen(context.Background(), "tcp", ":2121")
if err != nil {
return nil, err
}
return &ftpserver.Settings{ return &ftpserver.Settings{
ListenAddr: ":2121", // On fournit notre listener plutôt que ListenAddr
Listener: ln,
PublicHost: "163.172.68.103", PublicHost: "163.172.68.103",
PassiveTransferPortRange: &ftpserver.PortRange{ PassiveTransferPortRange: &ftpserver.PortRange{
Start: 30000, Start: 30000,
End: 30100, End: 30100,
}, },
Banner: "Bienvenue sur le FTP Go!", Banner: "Bienvenue sur le FTP Go!",
IdleTimeout: 0, IdleTimeout: 0, // ne pas couper côté serveur
ConnectionTimeout: 0, ConnectionTimeout: 10, // délai pour établir une connexion de transfert
}, nil }, nil
} }
@ -45,22 +72,27 @@ func (d *mainDriver) ClientConnected(cc ftpserver.ClientContext) (string, error)
log.Printf("[FTP] Nouvelle connexion depuis %s", cc.RemoteAddr()) log.Printf("[FTP] Nouvelle connexion depuis %s", cc.RemoteAddr())
return "Bienvenue FTP !", nil return "Bienvenue FTP !", nil
} }
func (d *mainDriver) ClientDisconnected(cc ftpserver.ClientContext) { func (d *mainDriver) ClientDisconnected(cc ftpserver.ClientContext) {
log.Printf("[FTP] Déconnexion client %s", cc.RemoteAddr()) log.Printf("[FTP] Déconnexion client %s", cc.RemoteAddr())
} }
func (d *mainDriver) GetTLSConfig() (*tls.Config, error) { func (d *mainDriver) GetTLSConfig() (*tls.Config, error) {
return nil, nil // Pas de TLS, à gérer si tu veux FTPS // Pas de TLS ici (FTPS), à ajouter si besoin
return nil, nil
} }
func (d *mainDriver) AuthUser(cc ftpserver.ClientContext, user, pass string) (ftpserver.ClientDriver, error) { func (d *mainDriver) AuthUser(cc ftpserver.ClientContext, user, pass string) (ftpserver.ClientDriver, error) {
log.Printf("[FTP] Tentative login user='%s' pass='%s'", user, pass) log.Printf("[FTP] Tentative login user='%s' pass='%s'", user, pass)
remoteAddr := cc.RemoteAddr().String() remoteAddr := cc.RemoteAddr().String()
host, _, _ := net.SplitHostPort(remoteAddr) host, _, _ := net.SplitHostPort(remoteAddr)
// 1. Compte user/pwd
if user == "cangui2089" && pass == "GHT30k7!" { if user == "cangui2089" && pass == "GHT30k7!" {
uploadPath, _ := filepath.Abs("upload") uploadPath, _ := filepath.Abs("upload")
fi, err := os.Stat(uploadPath) fi, err := os.Stat(uploadPath)
if err != nil || !fi.IsDir() { if err != nil || !fi.IsDir() {
log.Printf("[FTP] Le dossier upload/ est manquant ou non valide: %v", err) log.Printf("[FTP] Le dossier upload/ est manquant ou non valide : %v", err)
return nil, errors.New("le dossier upload/ doit exister") return nil, errors.New("le dossier upload/ doit exister")
} }
log.Printf("[FTP] Connexion OK, exposé: %s", uploadPath) log.Printf("[FTP] Connexion OK, exposé: %s", uploadPath)
@ -68,7 +100,8 @@ func (d *mainDriver) AuthUser(cc ftpserver.ClientContext, user, pass string) (ft
fs: afero.NewBasePathFs(afero.NewOsFs(), uploadPath), fs: afero.NewBasePathFs(afero.NewOsFs(), uploadPath),
}, nil }, nil
} }
// 2. Autoriser anonymous depuis 192.168.1.123 uniquement
// 2. Autoriser anonymous depuis IP spécifique
if user == "anonymous" && host == "82.65.73.115" { if user == "anonymous" && host == "82.65.73.115" {
base := filepath.Clean("upload") base := filepath.Clean("upload")
fs := afero.NewBasePathFs(afero.NewOsFs(), base) fs := afero.NewBasePathFs(afero.NewOsFs(), base)
@ -76,7 +109,7 @@ func (d *mainDriver) AuthUser(cc ftpserver.ClientContext, user, pass string) (ft
return &clientDriver{fs: fs}, nil return &clientDriver{fs: fs}, nil
} }
// 3. Sinon refuse tout anonyme ou mauvais login // 3. Refuser anonymous ou mauvais login
if user == "" || user == "anonymous" { if user == "" || user == "anonymous" {
log.Printf("[FTP] Login anonymous refusé pour %s", host) log.Printf("[FTP] Login anonymous refusé pour %s", host)
return nil, errors.New("anonymous login not allowed") return nil, errors.New("anonymous login not allowed")
@ -85,6 +118,16 @@ func (d *mainDriver) AuthUser(cc ftpserver.ClientContext, user, pass string) (ft
return nil, errors.New("identifiants invalides") return nil, errors.New("identifiants invalides")
} }
// ---- Extension: wrapper du listener passif (PASV) pour activer keep-alive ----
// WrapPassiveListener est appelée par ftpserverlib si le mainDriver
// implémente l'extension "MainDriverExtensionPassiveWrapper".
// On y met le même wrapper keep-alive que pour le listener principal.
func (d *mainDriver) WrapPassiveListener(l net.Listener) (net.Listener, error) {
log.Printf("[FTP] WrapPassiveListener: activation TCP keep-alive sur PASV")
return tcpKeepAliveListener{l}, nil
}
// ---------- clientDriver = wrapper sur afero.Fs ---------- // ---------- clientDriver = wrapper sur afero.Fs ----------
func (c *clientDriver) Name() string { return "aferofs" } func (c *clientDriver) Name() string { return "aferofs" }
@ -119,7 +162,6 @@ func (c *clientDriver) Chtimes(name string, atime, mtime time.Time) error {
return os.Chtimes(fullPath, atime, mtime) return os.Chtimes(fullPath, atime, mtime)
} }
// ---------- MAIN ---------- // ---------- MAIN ----------
func main() { func main() {
@ -150,5 +192,5 @@ func main() {
}) })
log.Println("[HTTP] Serveur Gin sur http://localhost:8080") log.Println("[HTTP] Serveur Gin sur http://localhost:8080")
app.Run(":8080") _ = app.Run(":8080")
} }