Heim  >  Artikel  >  Backend-Entwicklung  >  Stellen Sie über einen Proxy von Golang eine Verbindung zu FTP her

Stellen Sie über einen Proxy von Golang eine Verbindung zu FTP her

PHPz
PHPznach vorne
2024-02-09 12:00:09566Durchsuche

从 golang 通过代理连接到 ftp

PHP-Editor Zimo stellt Ihnen eine Methode vor, um mithilfe eines Proxys eine Verbindung zum Golang-Code des FTP-Servers herzustellen. In einigen Fällen müssen wir beim Zugriff auf den FTP-Server möglicherweise einen Proxyserver verwenden, um die Sicherheit zu erhöhen oder Netzwerkbeschränkungen aufzulösen. Golang ist eine leistungsstarke Programmiersprache mit benutzerfreundlichen Netzwerkbibliotheken, sodass wir diese Funktion problemlos implementieren können. Als Nächstes zeigen wir anhand eines einfachen Beispielcodes, wie Sie mit Golang über einen Proxy eine Verbindung zu einem FTP-Server herstellen.

Frageninhalt

Ich muss über einen Proxy eine Verbindung zum FTP-Server herstellen und Dateien vom Golang-Code herunterladen. Ich habe den einfachen Client implementiert:

<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>

Leider erhalte ich die Fehlermeldung 403 Forbidden, wenn ich versuche, eine Verbindung herzustellen. Normalerweise würde ich annehmen, dass dies eine Serverbeschränkung ist, aber über Curl funktioniert es einwandfrei :

curl -vvv -x 146.19.106.109:3128 -u dlpuser:rNrKYTX9g7z3RgJRmxWuGHbeu ftp://ftp.dlptest.com/xxx.txt

Weiß jemand, warum das passiert? Soweit ich weiß, verwendet Curl unter der Haube auch http CONNECT, daher frage ich mich, was ich übersehe.

P.S. Machen Sie sich keine Sorgen über die Anmeldeinformationen im Code – diese werden für Netzwerktests offengelegt.

Problemumgehung

FTP auf HTTP-Proxy erfolgt nicht über eine CONNECT-Anfrage. Stattdessen wird der Proxy angewiesen, die ftp://...-URL über eine normale GET-Anfrage abzurufen. Das ist es auch, was Curl tut. In Go kann das so gemacht werden (die Fehlerbehandlung wurde der Einfachheit halber weggelassen):

// 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)

Das obige ist der detaillierte Inhalt vonStellen Sie über einen Proxy von Golang eine Verbindung zu FTP her. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen