Editor PHP Zimo memperkenalkan anda kaedah untuk menyambung ke kod Golang pelayan FTP dengan menggunakan proksi. Dalam sesetengah kes, kami mungkin perlu menggunakan pelayan proksi apabila mengakses pelayan FTP untuk meningkatkan keselamatan atau menyelesaikan sekatan rangkaian. Golang ialah bahasa pengaturcaraan yang berkuasa dengan perpustakaan rangkaian yang mudah digunakan, jadi kami boleh melaksanakan ciri ini dengan mudah. Seterusnya, kami akan menggunakan kod sampel mudah untuk menunjukkan cara menggunakan Golang untuk menyambung ke pelayan FTP melalui proksi.
Saya perlu menyambung ke pelayan ftp melalui proksi dan memuat turun fail daripada kod Golang. Saya telah melaksanakan pelanggan mudah:
<code>package main import ( "bufio" "fmt" "github.com/jlaffaye/ftp" "io" "log" "net" "net/http" "os" "strings" "time" ) var targetAddr = "ftp.dlptest.com" var proxyAddr = "146.19.106.109:3128" var user = "dlpuser" var pass = "rNrKYTX9g7z3RgJRmxWuGHbeu" var path = "/xxx.txt" func connectViaProxy(network, address string) (net.Conn, error) { parts := strings.Split(address, ":") addr := fmt.Sprintf("%s:%s", targetAddr, parts[1]) proxyConn, err := net.Dial(network, proxyAddr) if err != nil { return nil, err } req, err := http.NewRequest(http.MethodConnect, "http://"+addr, nil) if err != nil { proxyConn.Close() return nil, err } req.Header.Set("Accept", "*/*") req.Header.Set("User-Agent", "curl/8.1.2") req.Header.Set("Host", targetAddr+":21") err = req.Write(proxyConn) if err != nil { return nil, err } resp, err := http.ReadResponse(bufio.NewReader(proxyConn), req) if err != nil { proxyConn.Close() return nil, err } if resp.StatusCode != 200 { x, _ := io.ReadAll(resp.Body) fmt.Println(string(x)) proxyConn.Close() return nil, fmt.Errorf("non-200 status code received from proxy: %v", resp.Status) } return proxyConn, nil } func main() { c, err := ftp.Dial(targetAddr+":21", ftp.DialWithTimeout(5*time.Second), ftp.DialWithDebugOutput(os.Stdin), ftp.DialWithDialFunc(connectViaProxy), ) if err != nil { log.Fatal(err) } err = c.Login(user, pass) if err != nil { log.Fatal(err) } if r, err := c.Retr(path); err != nil { fmt.Println(err, ":<") } else { if reader, err := io.ReadAll(r); err != nil { fmt.Println(err, ":(") } else { fmt.Println(string(reader)) } } if err = c.Quit(); err != nil { log.Fatal(err) } } </code>
Malangnya, saya mendapat 403 Forbidden apabila cuba menyambung. Biasanya saya akan menganggap ini adalah had pelayan, tetapi melalui curl ia berfungsi dengan baik :
curl -vvv -x 146.19.106.109:3128 -u dlpuser:rNrKYTX9g7z3RgJRmxWuGHbeu ftp://ftp.dlptest.com/xxx.txt
Adakah sesiapa tahu mengapa ini berlaku? Setahu saya, curl juga menggunakan http CONNECT di bawah tudung, jadi saya tertanya-tanya apa yang saya hilang.
P.S. Jangan risau tentang bukti kelayakan dalam kod - ini terdedah untuk ujian rangkaian
FTP pada proksi HTTP tidak dilakukan melalui permintaan CONNECT. Sebaliknya, proksi diarahkan untuk mendapatkan ftp://...
URL menggunakan permintaan GET biasa. Ini juga yang dilakukan oleh curl. Dalam Go, ia boleh dilakukan seperti ini (pengendalian ralat diabaikan untuk kesederhanaan):
// create the TCP connection to the proxy conn, err := net.Dial("tcp", "146.19.106.109:3128") // create the request with the ftp:// URL req, err := http.NewRequest(http.MethodGet, "ftp://ftp.dlptest.com/xxx.txt", nil) req.SetBasicAuth("dlpuser","rNrKYTX9g7z3RgJRmxWuGHbeu") // don't use req.Write but req.WriteProxy, since the request line must // contain the full URL and not only the path err = req.WriteProxy(conn) // read response resp, err := http.ReadResponse(bufio.NewReader(conn), req) body, _ := io.ReadAll(resp.Body)
Atas ialah kandungan terperinci Sambung ke ftp melalui proksi dari golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!