2014-10-20 2 views
0

Я хочу прокси-данные SSL, HTTPS в этом случае.ruby ​​SSL proxy (MITM)

Вот мой код:

begin 
     server = TCPServer.open(on_demand_port) 
rescue Exception => e 
     sleep 5 
     retry 
end 
sslContext = OpenSSL::SSL::SSLContext.new 
sslContext.verify_mode = OpenSSL::SSL::VERIFY_NONE 
begin 
    sslContext.cert = OpenSSL::X509::Certificate.new(File.open("#{Dir.pwd}/Cert/cert.pem")) 
    sslContext.key = OpenSSL::PKey::RSA.new(File.open("#{Dir.pwd}/Cert/key.pem"), "1234") 

rescue Exception => e 
     sleep 5 
     retry 
end 
begin 
    sslServer = OpenSSL::SSL::SSLServer.new(server, sslContext) 
rescue Exception => e 
     sleep 5 
     retry 
end 

while true 

    begin 
     threads << Thread.new(sslServer.accept) do |client| # Putting new connections into the thread pool 
     tcp_proxy(client, db_name, db_user, db_password, remote_host, remote_port, patterns) 
     end 
    rescue Exception => e 
    end 



    threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
     while threads.size >= on_demand_max_threads 
      sleep 1 
      threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
    end 
end 

И это "tcp_proxy", который является фактическим SSL Proxy

begin 
begin 
    ssl_context = OpenSSL::SSL::SSLContext.new 
    ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE 
    cert_store = OpenSSL::X509::Store.new 
    cert_store.set_default_paths 
    ssl_context.cert_store = cert_store 
    tcp_socket = TCPSocket.new(remote_host, remote_port) 
    server_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context 
    server_socket.sync_close = true 
    server_socket.connect 
rescue Exception => e 
      client.close 
end   
while true 
    # Wait for data to be available on either socket. 
    (ready_sockets, dummy, dummy) = IO.select([client, server_socket]) 
    begin 
     ready_sockets.each do |socket| 
      data = socket.readpartial(4096) 
      if socket == client 
       # Read from client, write to server. 
       server_socket.write data 
       server_socket.flush 
      else 
       # Read from server, write to client. 
       client.write data 
       client.flush 
      end 
    end 
    rescue Exception => e 
    end 
end 
    rescue StandardError => e 
    end 
    begin 
     client.close 
     server_socket.close 
    rescue Exception => e 
    end 

Теперь это работает прекрасно в обычном TCP и HTTP, но, когда я использую его в SSL \ HTTPS при обновлении сокета, он начинает получать действительно очень медленно, а иногда просто затягивается.

Любая идея, почему?

ответ

1

Вы должны быть осторожны с чтением и выбором, поскольку чтение выполняется на уровне SSL, а выбор - на уровне TCP.

SSL помещает данные в фреймы, где каждый кадр может содержать не более 16384 байт. Он должен прочитать полный кадр из основного TCP-сокета, прежде чем чтение в сокете SSL сможет вернуть любые данные из фрейма. Это означает, что если у вас есть фрейм с полезной нагрузкой 4097 байт, ему нужно будет прочитать полный кадр из сокета TCP, прежде чем вы сможете читать что-либо из сокета SSL. Если вы только прочитали 4096 байт из сокета SSL, он вернет первые 4096 байт и оставит остальные (1 байт) в буфере SSL. Если вы затем установите флажок для выбора новых данных на уровне TCP, он может блокироваться, потому что на уровне TCP нет непрочитанных данных, даже если в буфере SSL все еще есть один байт.

Есть два способа решения этой проблемы:

  • Проверить с pending, если есть еще данные в буфере SSL. Если есть, прочитайте их вместо того, чтобы делать выбор.
  • Или попробуйте прочитать по крайней мере 16384 байт с каждым чтением, то есть максимальный размер кадра SSL. Я не уверен в реализации в ruby, но в Perl это чтение просто вызовет базовый SSL_read, и это только считывает данные из одного кадра. Таким образом, с размером чтения 16384 байт не может быть ожидающих данных, и вы можете просто выбрать select, как сейчас.
+0

Использование IO.select и установка «read» на 16384, похоже, сработает, я буду изучать вложенный запрос, но на данный момент это делает трюк. – Ba7a7chy

Смежные вопросы