up
This commit is contained in:
parent
5b35c1d12e
commit
0ec0f33af6
62
main.go
62
main.go
@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user