Fix PASV address like lftp does (#349)
Some behind-firewall-and-corporate-network FTP servers responds their private-net address instead of the publicly reachable. This fix checks for such address and uses the command channel's address instead.
This commit is contained in:
parent
a58dc069db
commit
e44fc64e60
17
ftp.go
17
ftp.go
@ -528,9 +528,26 @@ func (c *ServerConn) pasv() (host string, port int, err error) {
|
|||||||
|
|
||||||
// Make the IP address to connect to
|
// Make the IP address to connect to
|
||||||
host = strings.Join(pasvData[0:4], ".")
|
host = strings.Join(pasvData[0:4], ".")
|
||||||
|
|
||||||
|
if c.host != host {
|
||||||
|
if cmdIP := net.ParseIP(c.host); cmdIP != nil {
|
||||||
|
if dataIP := net.ParseIP(host); dataIP != nil {
|
||||||
|
if isBogusDataIP(cmdIP, dataIP) {
|
||||||
|
return c.host, port, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return host, port, nil
|
return host, port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isBogusDataIP(cmdIP, dataIP net.IP) bool {
|
||||||
|
// Logic stolen from lftp (https://github.com/lavv17/lftp/blob/d67fc14d085849a6b0418bb3e912fea2e94c18d1/src/ftpclass.cc#L769)
|
||||||
|
return dataIP.IsMulticast() ||
|
||||||
|
cmdIP.IsPrivate() != dataIP.IsPrivate() ||
|
||||||
|
cmdIP.IsLoopback() != dataIP.IsLoopback()
|
||||||
|
}
|
||||||
|
|
||||||
// getDataConnPort returns a host, port for a new data connection
|
// getDataConnPort returns a host, port for a new data connection
|
||||||
// it uses the best available method to do so
|
// it uses the best available method to do so
|
||||||
func (c *ServerConn) getDataConnPort() (string, int, error) {
|
func (c *ServerConn) getDataConnPort() (string, int, error) {
|
||||||
|
22
ftp_test.go
Normal file
22
ftp_test.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package ftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBogusDataIP(t *testing.T) {
|
||||||
|
for _, tC := range []struct {
|
||||||
|
cmd, data net.IP
|
||||||
|
bogus bool
|
||||||
|
}{
|
||||||
|
{net.IPv4(192, 168, 1, 1), net.IPv4(192, 168, 1, 1), false},
|
||||||
|
{net.IPv4(192, 168, 1, 1), net.IPv4(1, 1, 1, 1), true},
|
||||||
|
{net.IPv4(10, 65, 1, 1), net.IPv4(1, 1, 1, 1), true},
|
||||||
|
{net.IPv4(10, 65, 25, 1), net.IPv4(10, 65, 8, 1), false},
|
||||||
|
} {
|
||||||
|
if got, want := isBogusDataIP(tC.cmd, tC.data), tC.bogus; got != want {
|
||||||
|
t.Errorf("%s,%s got %t, wanted %t", tC.cmd, tC.data, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user