Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Sambung ke ftp melalui proksi dari golang

Sambung ke ftp melalui proksi dari golang

PHPz
PHPzke hadapan
2024-02-09 12:00:09568semak imbas

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

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

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)

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

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam