Bagaimana cara menduplikasi lalu lintas TCP ke satu atau beberapa server jarak jauh untuk tujuan pembandingan?

30

Infrastruktur: Server di Datacenter, OS - Debian Squeeze, Webserver - Apache 2.2.16


Situasi:

Server langsung sedang digunakan oleh cusotmers kami setiap hari, yang membuatnya tidak mungkin untuk menguji penyesuaian dan peningkatan. Karenanya kami ingin menduplikasi lalu lintas HTTP masuk pada server langsung ke satu atau beberapa server jarak jauh secara realtime. Lalu lintas harus diteruskan ke server Web lokal (dalam hal ini Apache) DAN ke server jarak jauh. Dengan demikian kita dapat menyesuaikan konfigurasi dan menggunakan kode yang berbeda / diperbarui pada server jarak jauh untuk pembandingan dan perbandingan dengan server-hidup saat ini. Saat ini server web sedang mendengarkan sekitar. 60 port tambahan selain 80 dan 443, karena struktur klien.


Pertanyaan: Bagaimana duplikasi ini ke satu atau beberapa server jarak jauh diimplementasikan?

Kami sudah mencoba:

  • agnoster duplikator - ini akan membutuhkan satu sesi terbuka per port yang tidak berlaku. ( https://github.com/agnoster/duplicator )
  • kklis proxy - tidak hanya meneruskan lalu lintas ke server jauh, tetapi tidak meneruskannya ke server web lcoal. ( https://github.com/kklis/proxy )
  • iptables - DNAT hanya meneruskan lalu lintas, tetapi tidak meneruskannya ke server web lokal
  • iptables - TEE tidak hanya menggandakan ke server di jaringan lokal -> server tidak berada di jaringan yang sama karena struktur pusat data
  • alternatif yang disarankan disediakan untuk pertanyaan "duplikat tcp traffic dengan proksi" di stackoverflow ( https://stackoverflow.com/questions/7247668/duplicate-tcp-traffic-with-a-proxy ) tidak berhasil. Seperti yang disebutkan, TEE tidak bekerja dengan server jauh di luar jaringan lokal. teeproxy tidak lagi tersedia ( https://github.com/chrislusf/tee-proxy ) dan kami tidak dapat menemukannya di tempat lain.
  • Kami telah menambahkan alamat IP kedua (yang berada di jaringan yang sama) dan menetapkannya ke eth0: 0 (alamat IP primer ditugaskan ke eth0). Tidak berhasil menggabungkan IP baru ini atau antarmuka virtual eth0: 0 dengan fungsi atau rute iptables TEE.
  • alternatif yang disarankan disediakan untuk pertanyaan "duplikat lalu lintas tcp masuk pada debian squeeze" ( Gandakan lalu lintas TCP masuk pada Debian Squeeze ) tidak berhasil. Sesi kucing | nc (cat / tmp / prodpipe | nc 127.0.0.1 12345 dan cat / tmp / testpipe | nc 127.0.0.1 23456) terputus setelah setiap permintaan / terhubung oleh klien tanpa pemberitahuan atau log. Keepalive tidak mengubah situasi ini. Paket TCP tidak diangkut ke sistem jarak jauh.
  • Mencoba tambahan dengan opsi socat yang berbeda (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , https://stackoverflow.com/questions/9024227/duplicate-input- unix-stream-to-multiple-tcp-clients-using-socat ) dan alat-alat serupa tidak berhasil, karena fungsi TEE yang disediakan hanya akan menulis ke FS saja.
  • Tentu saja, googling dan mencari "masalah" atau penyiapan ini juga tidak berhasil.

Kami kehabisan opsi di sini.

Apakah ada metode untuk menonaktifkan penegakan "server di jaringan lokal" dari fungsi TEE saat menggunakan IPTABLES?

Bisakah tujuan kita dicapai dengan penggunaan IPTABLES atau Rute yang berbeda?

Apakah Anda tahu alat yang berbeda untuk tujuan ini yang telah diuji dan berfungsi untuk keadaan khusus ini?

Apakah ada sumber berbeda untuk tee-proxy (yang sesuai dengan kebutuhan kami, AFAIK)?


Terima kasih sebelumnya atas balasan Anda.

----------

sunting: 05.02.2014

di sini adalah skrip python, yang akan berfungsi seperti yang kita butuhkan:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

Komentar untuk menggunakan skrip ini: Skrip
ini meneruskan sejumlah port lokal yang dikonfigurasikan ke server socket lokal dan remote lainnya.

Konfigurasi:
Tambahkan ke file config port-forward.config baris dengan konten sebagai berikut:

Pesan kesalahan disimpan dalam file 'error.log'.

Script membagi parameter file config:
Pisahkan setiap config-line dengan spasi
0: port lokal untuk mendengarkan
1: port lokal untuk meneruskan ke
2: alamat ip jarak jauh dari server tujuan
3: port jarak jauh dari server tujuan
dan mengembalikan pengaturan

Sise
sumber
Apakah semua HTTP lalu lintas?
longneck
ya, semua lalu lintas adalah HTTP.
Sise
1
btw. teeproxy tersedia di sini: github.com/chrislusf/teeproxy
Tombart
1
Kemungkinan lain: github.com/ebowman/splitter Scala / Netty-based.
Rich K.

Jawaban:

11

Itu tidak mungkin. TCP adalah protokol statefull. Komputer pengguna akhir terlibat dalam setiap langkah koneksi dan tidak akan pernah menjawab dua server terpisah yang mencoba berkomunikasi dengannya. Yang bisa Anda lakukan adalah mengumpulkan semua permintaan http di server web atau beberapa proksi dan mengulanginya. Tapi itu tidak akan memberi dan tepat kondisi konkurensi atau lalu lintas dari server langsung.

Kazimieras Aliulis
sumber
Menduplikasi TCP tidak mungkin - Saya akan setuju dengan itu. Duplikat lalu lintas layer 7 tidak. Anda dapat menangkap permintaan dari klien dan memutarnya kembali ke server lain. Permintaan 1 sederhana per pemutaran sesi TCP seharusnya cukup mudah. Koneksi gigih akan membutuhkan beberapa pemikiran sejauh bagaimana Anda mengatur waktu permintaan tambahan klien.
Evan Anderson
@Kazimieras Aliulis: tidak perlu berkomunikasi dengan dua server terpisah. klien berkomunikasi dengan server utama = server langsung. server langsung sedang memproses permintaan klien dan menjawab klien. selain memproses dan menjawab ke klien server utama menduplikasi permintaan ke server kedua = server pengujian. tanggapan dari server kedua ke server utama akan dibuang / diabaikan di server utama dan tidak akan diteruskan ke klien.
Sise
@ Evan Anderson: duplikasi pada level HTTP adalah ide pertama kami juga, tetapi mis. Apache proxy atau alat atau modul serupa tidak memungkinkan secara bersamaan memproses permintaan secara lokal dan menduplikasinya ke host jarak jauh. jika Anda memiliki ide lain, mohon saran! :) kami lebih memilih duplikasi daripada merekam dan memutar ulang untuk mendapatkan hasil perbandingan instan.
Sise
1
@Sise: Anda dapat mencoba menulis proksi http Anda sendiri, yang meneruskan lalu lintas ke dua server. Seharusnya cukup mudah dilakukan dengan python Twisted framework twistedmatrix.com .
Kazimieras Aliulis
@Kimimieras Aliulis: itu pasti sebuah alternatif! saya belum pernah mendengarnya. tetapi memeriksanya menunjukkan bahwa itu akan pas dengan tujuan kita. Kami tidak mempertimbangkan python sebelumnya, tetapi saat ini kami sedang melihat kerangka Twisted dan kemungkinan dengan python umum juga. Saya akan melaporkan kembali jika kita berhasil!
Sise
20

Dari apa yang Anda jelaskan, GOR tampaknya sesuai dengan kebutuhan Anda. https://github.com/buger/gor/ "replay lalu lintas HTTP secara real-time. Putar ulang lalu lintas dari produksi ke lingkungan pementasan dan pengembangan." ?

Arthur Lutz
sumber
2
Ini persis apa yang saya cari, terima kasih banyak, Anda menyelamatkan saya menulis ini, di Go! :-)
chmac
nginx memiliki modul cermin. nginx.org/en/docs/http/ngx_http_mirror_module.html
Jimmy MG Lim
7

Teeproxy dapat digunakan untuk mereplikasi traffic. Penggunaannya sangat sederhana:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a server produksi
  • b server pengujian

Ketika Anda menempatkan HAproxy (dengan roundrobin) di depan server web Anda, Anda dapat dengan mudah mengarahkan 50% dari lalu lintas Anda ke situs pengujian:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)
Tombart
sumber
4

TCP, sebagai protokol stateful, tidak dapat menerima peledakan salinan paket di host lain, seperti yang ditunjukkan oleh @KazimierasAliulis.

Mengambil paket pada lapisan terminasi TCP dan menyampaikannya sebagai aliran TCP baru adalah masuk akal. Alat duplikator yang Anda tautkan sepertinya adalah taruhan terbaik Anda. Ini beroperasi sebagai proksi TCP, memungkinkan mesin negara TCP untuk beroperasi dengan baik. Respons dari mesin uji Anda hanya akan dibuang. Kedengarannya cocok dengan tagihan untuk apa yang Anda inginkan sebenarnya.

Tidak jelas bagi saya mengapa Anda telah menghapus alat duplikator sebagai tidak dapat diterima. Anda harus menjalankan beberapa instance alat karena hanya mendengarkan pada satu port tetapi, mungkin, Anda ingin merelay masing-masing port mendengarkan yang berbeda ke port yang berbeda pada sistem back-end. Jika tidak, Anda bisa menggunakan DNAT iptables untuk mengarahkan semua port mendengarkan ke salinan tunggal dari alat duplikator.

Kecuali jika aplikasi yang Anda uji sangat sederhana, saya berharap Anda akan memiliki masalah dengan metodologi pengujian yang berkaitan dengan waktu dan status aplikasi internal. Apa yang ingin Anda lakukan terdengar menipu sederhana - saya berharap Anda akan menemukan banyak kasus tepi.

Evan Anderson
sumber
ya, Anda sepenuhnya benar, alat duplikator agnoster akan sesuai dengan persyaratan kami kecuali situasi multi-port. Juga membuang tanggapan mesin uji terpenuhi. Untuk mencapai tujuan kami mensimulasikan situasi nyata / langsung seakurat mungkin, kami tidak dapat menggabungkan semua port di server langsung ke satu port tunggal pada mesin uji. Port yang berbeda digunakan untuk membagi perangkat klien menjadi pelanggan yang berbeda. Dengan demikian, kita harus membuka 60-70 sesi alat duplikator ini. Ini tidak terlalu praktis seperti yang Anda bayangkan.
Sise
@Sise - Komputer pandai melakukan hal-hal yang membosankan. Saya pikir Anda bisa menulis skrip untuk mem-parsing konfigurasi Apache Anda dan memuntahkan baris perintah yang diperlukan untuk menjalankan 60 - 70 contoh alat duplikator. Saya tidak bisa membayangkan alat duplikator sangat intensif sumber daya tetapi, bahkan jika itu, Anda bisa menjalankan contoh 60 - 70 di komputer lain dan melakukan beberapa tipu daya jaringan untuk mendapatkan lalu lintas di sana. Bagi saya, setidaknya, itu tampaknya sepenuhnya praktis dan cara yang cukup mudah untuk menangani ini.
Evan Anderson
1

Saya mencoba melakukan sesuatu yang serupa, namun, jika Anda hanya mencoba untuk mensimulasikan beban pada server saya akan melihat sesuatu seperti kerangka kerja pengujian beban. Saya telah menggunakan locust.io di masa lalu dan bekerja sangat baik untuk mensimulasikan beban di server. Itu akan memungkinkan Anda untuk mensimulasikan sejumlah besar klien dan membiarkan Anda bermain dengan konfigurasi server tanpa harus melalui proses yang menyakitkan untuk meneruskan lalu lintas ke server lain.

snowbirdSkiBum
sumber
0

Sejauh "kami ingin menduplikasi lalu lintas HTTP masuk pada server langsung ke satu atau beberapa server jarak jauh secara realtime", ada satu cara yang tidak disebutkan di atas, yaitu mengkonfigurasi port mirror pada sakelar yang terhubung dengannya.

Dalam kasus switch Cisco Catalyst, ini disebut SPAN (info lebih lanjut di sini ). Dalam lingkungan Cisco Anda bahkan dapat memiliki port mirror pada switch yang berbeda.

Tetapi tujuan dari ini adalah untuk analisis lalu lintas sehingga akan menjadi uni-directional - kata kunci dalam teks yang dikutip dalam paragraf pertama di atas: inbound . Saya tidak berpikir bahwa port akan memungkinkan lalu lintas kembali, dan jika itu terjadi, bagaimana Anda akan menangani lalu lintas kembali duplikat? Itu mungkin hanya akan mendatangkan malapetaka pada jaringan Anda.

Jadi ... hanya ingin menambahkan satu kemungkinan ke daftar Anda, tetapi dengan peringatan bahwa itu memang untuk lalu lintas satu arah. Mungkin Anda dapat menempatkan hub pada port mirror itu dan memiliki balasan server duplikat yang diserahkan oleh beberapa simulator klien lokal yang akan mengambil sesi yang dimulai dan merespons, tetapi kemudian Anda akan menduplikasi lalu lintas masuk ke server duplikat Anda ... mungkin bukan apa yang Anda ingin.

James
sumber
kami telah memikirkan hal itu, saya telah membaca tentang alternatif menggunakan SPAN. Namun, karena server terletak di pusat data penyedia pihak ketiga, kami memiliki kemungkinan terbatas ketika datang ke perubahan perangkat keras. Saya sudah meminta untuk menghubungkan 2 server pada nic kedua secara langsung. Tindakan ini dikombinasikan dengan jaringan lokal untuk hanya 2 server ini akan memungkinkan saya untuk menggunakan IPTABLES dengan TEE. Tetapi untuk mencari alternatif ini kita perlu mengubah IP eksternal dari server, yang merupakan NoGo karena perangkat klien dikonfigurasi untuk terhubung ke IP yang ditetapkan.
Sise
0

Saya juga telah menulis reverse proxy / load balancer untuk tujuan yang sama dengan Node.js (hanya untuk bersenang-senang, bukan produksi yang siap saat ini).

https://github.com/losnir/ampel

Ini sangat beralasan, dan saat ini mendukung:

  • GET Menggunakan pilihan round-robin (1: 1)
  • POSTMenggunakan pemisahan permintaan. Tidak ada konsep "master" dan "bayangan" - backend pertama yang merespons adalah yang akan melayani permintaan klien, dan kemudian semua respons lainnya akan dibuang.

Jika seseorang menganggapnya berguna maka saya dapat memperbaikinya agar lebih fleksibel.

losnir
sumber
Node.js adalah pilihan bahasa yang sangat aneh untuk aplikasi seperti ini yang akan membutuhkan kinerja yang sangat tinggi. Saya tidak yakin ini akan siap produksi.
Michael Hampton
Anda benar sekali. Ini tidak dimaksudkan untuk menjadi sangat berkinerja tinggi - hanya mudah untuk menulis (untuk saya). Saya pikir itu tergantung pada beban yang diperlukan. Saya dapat mencapai sedikit lebih dari 1.000rps pada mesin low end (2 core).
losnir
0

perusahaan saya memiliki persyaratan yang sama, untuk mengkloning suatu paket dan mengirim ke host lain (kami menjalankan simulator data pasar dan membutuhkan solusi sementara yang akan mendengarkan umpan data pasar TCP, menelan setiap paket tetapi juga mengirim klon dari setiap paket ke simulator lain server)

biner ini berjalan sangat baik, ini adalah versi TCP Duplicator tetapi ditulis dalam golang bukan jscript, jadi jalannya lebih cepat, dan berfungsi seperti yang diiklankan,

https://github.com/mkevac/goduplicator

perfecto25
sumber
-1

ada alat yang dibuat oleh seorang pria dari perusahaan Cina, dan mungkin itu yang Anda butuhkan: https://github.com/session-replay-tools/tcpcopy

Musikoder
sumber
2
Hai dan selamat datang di serverfault. Bisakah Anda memberikan jawaban yang lebih detail? Apa tepatnya yang dilakukan program? Apakah ini ditulis dalam C ...?
bgtvfr