Bagikan melalui


Menggunakan Ikat atau Sambungkan Pengalihan

Fitur pengalihan sambungkan/ikatan dari Windows Filtering Platform (WFP) memungkinkan driver callout penerapan lapisan aplikasi (ALE) untuk memeriksa dan, jika diinginkan, mengalihkan koneksi.

Fitur ini tersedia di Windows 7 dan yang lebih baru.

Catatan Modul ClassifyFunctions_ProxyCallouts.cpp dalam sampel driver WFP menyertakan kode yang menunjukkan pengalihan sambungkan/ikat.

Callout pengalihan koneksi WFP mengalihkan permintaan koneksi aplikasi sehingga aplikasi terhubung ke layanan proksi alih-alih tujuan asli. Layanan proksi memiliki dua soket: satu untuk koneksi asli yang dialihkan dan satu untuk koneksi keluar yang diproksikan baru.

Catatan pengalihan WFP adalah buffer data buram yang harus diatur WFP pada koneksi proksi keluar di lapisan FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 dan FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6 , sehingga koneksi yang dialihkan dan koneksi asli terkait secara logis.

Mengubah alamat lokal dan port alur hanya didukung di lapisan pengalihan ikatan. Ini tidak didukung di lapisan pengalihan koneksi.

Lapisan yang Digunakan untuk Pengalihan

Pengalihan dapat dilakukan oleh driver callout pada lapisan berikut, yang disebut "lapisan pengalihan":

  • FWPM_LAYER_ALE_BIND_REDIRECT_V4 (FWPS_LAYER_ALE_BIND_REDIRECT_V4)

  • FWPM_LAYER_ALE_BIND_REDIRECT_V6 (FWPS_LAYER_ALE_BIND_REDIRECT_V6)

  • FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 (FWPS_LAYER_ALE_CONNECT_REDIRECT_V4)

  • FWPM_LAYER_ALE_CONNECT_REDIRECT_V6 (FWPS_LAYER_ALE_CONNECT_REDIRECT_V6)

Lapisan di mana pengalihan dilakukan menentukan efek perubahan. Perubahan pada lapisan sambungkan hanya memengaruhi alur yang tersambung. Perubahan pada lapisan ikat memengaruhi semua koneksi yang menggunakan soket tersebut.

Lapisan pengalihan hanya tersedia untuk Windows 7 dan versi Windows yang lebih baru. Driver callout yang mendukung klasifikasi pada lapisan ini harus mendaftar menggunakan FwpsCalloutRegister1 atau yang lebih tinggi, bukan fungsi FwpsCalloutRegister0 yang lebih lama.

Penting

 Pengalihan tidak tersedia untuk digunakan dengan semua jenis lalu lintas jaringan. Jenis paket yang didukung untuk pengalihan diperlihatkan dalam daftar berikut:

  • TCP
  • UDP
  • UDPv4 mentah tanpa opsi sertakan header
  • ICMP Mentah

Melakukan Pengalihan

Untuk mengalihkan koneksi, driver callout harus mendapatkan salinan informasi TCP 4-tuple yang dapat ditulis, membuat perubahan sesuai kebutuhan, dan menerapkan perubahan. Satu set fungsi baru disediakan untuk mendapatkan data lapisan bisa-tulis dan untuk menerapkannya melalui mesin. Driver callout memiliki opsi untuk membuat perubahan sebaris dalam fungsi classifyFn mereka, atau secara asinkron dalam fungsi lain.

Driver callout yang menerapkan pengalihan harus menggunakan classifyFn1 atau yang lebih baru alih-alih classifyFn0 sebagai fungsi callout klasifikasi mereka. Untuk menggunakan classifyFn1 atau yang lebih baru, callout harus didaftarkan dengan memanggil FwpsCalloutRegister1 atau yang lebih baru, bukan FwpsCalloutRegister0 yang lebih lama.

Untuk melakukan pengalihan sebaris driver callout harus melakukan langkah-langkah berikut dalam implementasi classifyFn:

  1. Panggil FwpsRedirectHandleCreate0 untuk mendapatkan handel yang dapat digunakan untuk mengalihkan koneksi TCP. Handel ini harus di-cache dan digunakan untuk semua pengalihan. (Langkah ini dihilangkan untuk Windows 7 dan yang lebih lama.)

  2. Di Windows 8 dan yang lebih baru, Anda harus mengkueri status pengalihan koneksi dengan menggunakan fungsi FwpsQueryConnectionRedirectState0 di driver callout Anda. Ini harus dilakukan untuk mencegah pengalihan tak terbatas.

  3. Panggil FwpsAcquireClassifyHandle0 untuk mendapatkan handel yang akan digunakan untuk panggilan fungsi berikutnya.

  4. Panggil FwpsAcquireWritableLayerDataPointer0 untuk mendapatkan struktur data bisa-tulis untuk lapisan tempat classifyFn dipanggil. Transmisikan parameter writableLayerData ke struktur yang sesuai dengan lapisan, baik FWPS_BIND_REQUEST0 atau FWPS_CONNECT_REQUEST0.

    Dimulai dengan Windows 8, jika driver callout Anda dialihkan ke layanan lokal, Anda harus memanggil FwpsRedirectHandleCreate0 untuk mengisi anggota localRedirectHandle dari struktur FWPS_CONNECT_REQUEST0 untuk membuat pekerjaan proksi lokal.

  5. Buat perubahan pada data lapisan sesuai kebutuhan:

    1. Simpan tujuan asli dalam konteks pengalihan lokal seperti yang ditunjukkan dalam contoh berikut:

      FWPS_CONNECT_REQUEST* connectRequest = redirectContext->connectRequest;
      // Replace "..." with your own redirect context size
      connectRequest->localRedirectContextSize = ...;
      // Store original destination IP/Port information in the localRedirectContext member
      connectRequest->localRedirectContext =    ExAllocatePoolWithTag(…);
      
    2. Ubah alamat jarak jauh seperti yang ditunjukkan dalam contoh berikut:

      // Ensure we don't need to worry about crossing any of the TCP/IP stack's zones
      if(INETADDR_ISANY((PSOCKADDR)&(connectRequest->localAddressAndPort)))
      {
         INETADDR_SETLOOPBACK((PSOCKADDR)&(connectRequest->remoteAddressAndPort));
      }
      else
      {
         INETADDR_SET_ADDRESS((PSOCKADDR)&(connectRequest->remoteAddressAndPort),
                               INETADDR_ADDRESS((PSOCKADDR)&(connectRequest->localAddressAndPort)));
      }
      INETADDR_SET_PORT((PSOCKADDR)&connectRequest->remoteAddressAndPort,
                        RtlUshortByteSwap(params->proxyPort));
      
    3. Jika driver callout Anda mengalihkan ke layanan lokal, driver tersebut harus mengatur PID proksi lokal di anggota localRedirectTargetPID dari struktur FWPS_CONNECT_REQUEST0 .

    4. Jika driver callout Anda mengalihkan ke layanan lokal, driver tersebut harus mengatur handel pengalihan yang dikembalikan oleh FwpsRedirectHandleCreate0 di anggota localRedirectHandle dari struktur FWPS_CONNECT_REQUEST0.

  6. Panggil FwpsApplyModifiedLayerData0 untuk menerapkan perubahan yang dilakukan pada data.

  7. Di layanan proksi Anda (yang bisa dalam mode pengguna atau mode kernel), Anda harus mengkueri rekaman dan konteks pengalihan seperti yang ditunjukkan dalam contoh berikut:

    BYTE* redirectRecords;
    BYTE redirectContext[CONTEXT_SIZE];
    listenSock = WSASocket(…);
    result = bind(listenSock, …);
    result = listen(listenSock, …);
    clientSock = WSAAccept(listenSock, …);
    // opaque data to be set on proxy connection
    result = WSAIoctl(clientSock,
                      SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS,
                      redirectRecords, …);
    // callout allocated data, contains original destination information
    result = WSAIoctl(clientSock,
                      SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT,
                      redirectContext, …);
    // extract original destination IP and port from above context
    
  8. Di layanan proksi Anda (yang bisa dalam mode pengguna atau mode kernel), Anda harus mengatur rekaman pengalihan pada soket koneksi proksi seperti yang ditunjukkan dalam contoh berikut untuk membuat soket keluar baru:

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. Panggil FwpsReleaseClassifyHandle0 untuk merilis handel klasifikasi yang diperoleh pada langkah 2.

  10. Panggil FwpsRedirectHandleDestroy0 untuk menghancurkan handel yang diperoleh di langkah 1.

Untuk melakukan pengalihan secara asinkron, driver callout harus melakukan langkah-langkah berikut:

  1. Panggil FwpsRedirectHandleCreate0 untuk mendapatkan handel yang dapat digunakan untuk mengalihkan koneksi TCP. (Langkah ini dihilangkan untuk Windows 7 dan yang lebih lama.)

  2. Di Windows 8 dan yang lebih baru, Anda harus mengkueri status pengalihan koneksi dengan menggunakan fungsi FwpsQueryConnectionRedirectState0 di driver callout Anda.

  3. Panggil FwpsAcquireClassifyHandle0 untuk mendapatkan handel yang akan digunakan untuk panggilan fungsi berikutnya. Langkah dan langkah 2 dan 3 ini dilakukan dalam fungsi callout classifyFn driver callout.

  4. Panggil FwpsPendClassify0 untuk menempatkan klasifikasi dalam status tertunda seperti yang ditunjukkan dalam contoh berikut:

    FwpsPendClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_BLOCK;
    classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    

Catatan

Jika Anda menargetkan Windows 7, Anda harus melakukan langkah-langkah berikut dalam fungsi pekerja terpisah. Jika Anda menargetkan Windows 8 atau yang lebih baru, Anda dapat melakukan semua langkah untuk pengalihan asinkron dari dalam classifyFn dan mengabaikan Langkah 5.

  1. Kirim handel klasifikasi dan data lapisan bisa-tulis ke fungsi lain untuk pemrosesan asinkron. Langkah-langkah yang tersisa dilakukan dalam fungsi itu, bukan dalam implementasi driver callout dari classifyFn.

  2. Panggil FwpsAcquireWritableLayerDataPointer0 untuk mendapatkan struktur data bisa-tulis untuk lapisan tempat classifyFn dipanggil. Transmisikan parameter writableLayerData ke struktur yang sesuai dengan lapisan, baik FWPS_BIND_REQUEST0 atau FWPS_CONNECT_REQUEST0.

    Dimulai dengan Windows 8, jika driver callout Anda dialihkan secara lokal, Anda harus memanggil FwpsRedirectHandleCreate0 untuk mengisi anggota localRedirectHandle dari struktur FWPS_CONNECT_REQUEST0 untuk membuat pekerjaan proksi.

  3. Simpan informasi konteks khusus callout apa pun dalam struktur konteks privat seperti yang ditunjukkan dalam contoh berikut:

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. Buat perubahan pada data lapisan sesuai kebutuhan.

  5. Panggil FwpsApplyModifiedLayerData0 untuk menerapkan perubahan yang dilakukan pada data. Atur bendera FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS jika Anda ingin diotorisasi ulang jika callout lain memodifikasi data lebih lanjut.

  6. Panggil FwpsCompleteClassify0 untuk menyelesaikan operasi klasifikasi secara asinkron seperti yang ditunjukkan dalam contoh berikut:

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. Panggil FwpsReleaseClassifyHandle0 untuk merilis handel klasifikasi yang diperoleh di langkah 1.

Menangani Pengalihan Connect dari Beberapa Callout

Ada kemungkinan bahwa lebih dari satu driver callout akan memulai pengalihan koneksi untuk alur yang sama. Callout yang melakukan pengalihan koneksi harus mengetahui permintaan lain dan merespons dengan tepat.

Bendera FWPS_RIGHT_ACTION_WRITE harus diatur setiap kali panggilan menunggu klasifikasi. Callout Anda harus menguji bendera FWPS_RIGHT_ACTION_WRITE untuk memeriksa hak bagi callout Anda untuk mengembalikan tindakan. Jika bendera ini tidak diatur, callout Anda masih dapat mengembalikan tindakan FWP_ACTION_BLOCK untuk mem-veto tindakan FWP_ACTION_PERMIT yang dikembalikan oleh callout sebelumnya.

Di Windows 8 dan yang lebih baru, driver callout Anda harus meminta status pengalihan koneksi (untuk melihat apakah driver callout Anda atau driver callout lain telah memodifikasinya) dengan menggunakan fungsi FwpsQueryConnectionRedirectState0. Jika koneksi dialihkan oleh driver callout Anda, atau jika sebelumnya dialihkan oleh driver callout Anda, driver callout tidak boleh melakukan apa pun. Jika tidak, ini juga harus memeriksa pengalihan lokal seperti yang ditunjukkan dalam contoh berikut:

FwpsAcquireWritableLayerDataPointer(...,(PVOID*)&connectRequest), ...);
if(connectRequest->previousVersion->modifierFilterId != filterId)
{
    if(connectRequest->previousVersion->localRedirectHandle)
    {
        classifyOut->actionType = FWP_ACTION_PERMIT;
        classifyOut->rights &= FWPS_RIGHT_ACTION_WRITE;
        FwpsApplyModifiedLayerData(
                classifyHandle,
                (PVOID)connectRequest,
                FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS);
    }
}

Jika koneksi ke proksi lokal, driver callout Anda tidak boleh mencoba mengalihkannya.

Driver callout yang menggunakan pengalihan koneksi harus mendaftar di lapisan koneksi otorisasi ALE (FWPS_LAYER_ALE_AUTH_CONNECT_V4 atau FWPS_LAYER_ALE_AUTH_CONNECT_V6) dan memeriksa dua nilai metadata berikut untuk indikasi di mana bendera FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED diatur:

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID berisi pengidentifikasi proses untuk proses yang bertanggung jawab atas alur yang dialihkan.

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION berisi alamat tujuan asli untuk alur.

Struktur FWPS_CONNECT_REQUEST0 berisi anggota yang disebut localRedirectTargetPID. Agar pengalihan koneksi loopback valid, bidang ini harus diisi dengan PID proses yang akan bertanggung jawab atas alur yang dialihkan. Ini adalah data yang sama dengan yang diteruskan mesin pada lapisan koneksi otorisasi ALE seperti FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID.

Dimulai dengan Windows 8, layanan proksi perlu mengeluarkan IOCTL SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS dan SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT, menggunakan WSAIoctl, terhadap titik akhir asli layanan proksi. Selain itu, SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL harus dikeluarkan, menggunakan WSAIoctl, pada soket baru (proksi).

Nama Version-Independent WFP dan Penargetan Versi Windows Tertentu