Sambung ke ftp melalui proksi dari golang

PHPz
Lepaskan: 2024-02-09 12:00:09
ke hadapan
605 orang telah melayarinya

从 golang 通过代理连接到 ftp

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.

Kandungan soalan

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>
Salin selepas log masuk

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
Salin selepas log masuk

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

Penyelesaian

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)
Salin selepas log masuk

Atas ialah kandungan terperinci Sambung ke ftp melalui proksi dari golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan