Как использовать прокси-сервер с Ruby Net::FTP?

Я использую библиотеку Net::FTP ruby ​​для подключения к FTP-серверу и загрузки файлов. Все работает хорошо, но теперь мне нужно использовать исходящий прокси, так как их белый список IP-адресов брандмауэра, и я использую Heroku для размещения сайта. Я пробую новое дополнение Proximo, которое выглядит многообещающим, но я не могу заставить Net:: FTP использовать его.

В документации Net:: FTP я вижу следующее:

подключиться (хост, порт = FTP_PORT)

Устанавливает FTP-соединение с хостом, опционально перекрывая порт по умолчанию. Если установлена ​​переменная окружения SOCKS_SERVER, устанавливает соединение через прокси SOCKS. Вызывает исключение (обычно Errno::ECONNREFUSED), если не удается установить соединение.

Но пытаясь установить эту переменную среды, или настройка ENV['SOCKS_SERVER'] = proximo_url тоже не работает. Кто-нибудь знает, как правильно это сделать? Это не обязательно должен быть прокси-сервер SOCKS, подойдет HTTP-прокси, но я не уверен, что библиотека Net:: FTP поддерживает это.

... после некоторых исследований...

Я обнаружил, что Net:: FTP ищет класс с именем SOCKSSocket, для которого я нашел эти документы. Но я не могу включить это. include 'socket' возвращает false, что, я уверен, означает, что оно уже загружено.

4 ответа

Вы можете использовать драгоценный камень socksify как в сочетании с например. Quotaguard. Убедитесь, что вы используете один из предоставленных статических IP-адресов (а не имя хоста DNS) в качестве прокси-сервера, поскольку FTP и балансировка нагрузки могут вызвать проблемы.

Socksify::debug = true
proxy_uri = URI(ENV['QUOTAGUARDSTATIC_URL'])
proxy_hostname = proxy_uri.hostname
proxy_port = 1080
TCPSocket::socks_username = proxy_uri.user
TCPSocket::socks_password = proxy_uri.password
Socksify::proxy(proxy_hostname, proxy_port) do |soc| 
       Net::FTP.open(server) do |ftp|
            ftp.passive = true
            ftp.debug_mode = true 
            ftp.login user, password
            ftp.get(export, storelocation)
            ftp.close
       end
end

Это мой взгляд на проблему. Котельная плита:

# Connects to ftp through a socks proxy
#
# TODO: testing, use ssl, capture debugging output, recovery on network failure...
#
# @param ftpHost   [String ] Domain name or ip address of the ftp server
# @param proxyHost [String ] Host name or ip address of the socks proxy
# @param proxyPort [FixNum ] Port number of the socks proxy
# @param proxyUser [String ] User name for connecting to the proxy if needed
# @param proxyPass [String ] Password  for connecting to the proxy if needed
# @param ftpPort   [FixNum ] Ftp port, defaults to 21
# @param ftpUser   [String ] Ftp username
# @param ftpPass   [String ] Ftp password
# @param debug     [Boolean] Whether to turn on debug output of both socksify and Net::FTP, will be sent to STDOUT
# @param passive   [Boolean] Whether to use passive FTP mode
#
def ftp(

        ftpHost:                      ,
        proxyHost:                    ,
        proxyPort:                    ,
        proxyUser: nil                ,
        proxyPass: nil                ,
        ftpPort:   Net::FTP::FTP_PORT ,
        ftpUser:   'anonymous'        ,
        ftpPass:   'anonymous@'       ,
        debug:     false              ,
        passive:   true

    )

    Socksify::debug           = debug
    TCPSocket::socks_username = proxyUser
    TCPSocket::socks_password = proxyPass

    Socksify::proxy( proxyHost, proxyPort ) do |_|

        begin

            # Check whether we got an ip address or a domain name.
            # If needed we'll do dns through the socket to avoid dns leaks.
            #
            Regexp.new( URI::RFC2396_Parser.new.pattern[ :IPV4ADDR ] ) =~ ftpHost  or

                ftpHost = Socksify::resolve( ftpHost )


            ftp            = Net::FTP.new
            ftp.debug_mode = debug
            ftp.passive    = passive

            ftp.connect ftpHost, ftpPort
            ftp.login   ftpUser, ftpPass

            yield ftp

        ensure

            ftp.close

        end

    end

end

Теперь в вашем реальном приложении вы можете просто:

def listRemoteFiles

    connect do |ftp|

        puts ftp.list.inspect  # or other cool functions from Net::FTP

    end

end


def connect &block

    ftp({

        debug:     true            ,
        proxyHost: your.proxy.host ,
        proxyPort: your.proxy.port ,
        ftpHost:   your.ftpHost 

    }, &block )

end

Спасибо tvgriek за указание в правильном направлении.

Может быть, эта ссылка может быть вам полезна?

https://github.com/plevel/ruby-ftp-proxy

Вы можете использовать оболочку Proximo для пересылки трафика через Proximo. Вот официальные инструкции: https://devcenter.heroku.com/articles/proximo

Другие вопросы по тегам