Konfigurasikan ASP.NET Core agar berfungsi dengan server proksi dan penyeimbang beban
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Oleh Chris Ross
Dalam konfigurasi yang direkomendasikan untuk ASP.NET Core, aplikasi dihosting menggunakan ASP.NET Core Module (ANCM) untuk IIS, Nginx, atau Apache. Server proksi, load balancer, dan appliance jaringan lainnya sering mengaburkan informasi tentang permintaan sebelum mencapai aplikasi:
- Ketika permintaan HTTPS diproksi melalui HTTP, skema asli (HTTPS) hilang dan harus diteruskan di header.
- Karena aplikasi menerima permintaan dari proksi dan bukan sumber sebenarnya di Internet atau jaringan perusahaan, alamat IP klien asal juga harus diteruskan di header.
Informasi ini mungkin penting dalam pemrosesan permintaan, misalnya dalam pengalihan, autentikasi, pembuatan tautan, evaluasi kebijakan, dan geolokasi klien.
Aplikasi yang dimaksudkan untuk dijalankan di farm web harus membaca Host ASP.NET Core di farm web.
Header yang diteruskan
Menurut konvensi, proksi meneruskan informasi di header HTTP.
Header | Deskripsi |
---|---|
X-Forwarded-For (XFF) |
Menyimpan informasi tentang klien yang memulai permintaan dan proksi berikutnya dalam rantai proksi. Parameter ini mungkin berisi alamat IP dan, secara opsional, nomor port. Dalam rantai server proksi, parameter pertama menunjukkan klien tempat permintaan pertama kali dibuat. Pengidentifikasi proksi berikutnya mengikuti. Proksi terakhir dalam rantai tidak ada dalam daftar parameter. Alamat IP proksi terakhir, dan secara opsional nomor port, tersedia sebagai alamat IP jarak jauh di lapisan transportasi. |
X-Forwarded-Proto (XFP) |
Nilai skema asal, HTTP atau HTTPS. Nilai mungkin juga merupakan daftar skema jika permintaan telah melintasi beberapa proksi. |
X-Forwarded-Host (XFH) |
Nilai asli bidang header Host. Biasanya, proksi tidak mengubah header Host. Lihat Microsoft Security Advisory CVE-2018-0787 untuk informasi tentang kerentanan elevasi hak istimewa yang memengaruhi sistem di mana proksi tidak memvalidasi atau membatasi header Host ke nilai yang diketahui baik. |
X-Forwarded-Prefix |
Jalur dasar asli yang diminta oleh klien. Header ini dapat berguna bagi aplikasi untuk menghasilkan URL, pengalihan, atau tautan dengan benar kembali ke klien. |
Middleware Header yang Diteruskan, ForwardedHeadersMiddleware, membaca header ini dan mengisi bidang terkait pada HttpContext.
Pembaruan middleware:
HttpContext.Connection.RemoteIpAddress
: AturX-Forwarded-For
menggunakan nilai header. Pengaturan tambahan memengaruhi bagaimana middleware diaturRemoteIpAddress
. Untuk detailnya, lihat opsi Middleware Header yang Diteruskan. Nilai yang digunakan dihapus dariX-Forwarded-For
, dan nilaiHttpContext.Connection.RemoteIpAddress
lama dipertahankan dalamX-Original-For
. Catatan: Proses ini dapat diulang beberapa kali jika ada beberapa nilai dalamX-Forwarded-For/Proto/Host/Prefix
, yang mengakibatkan beberapa nilai dipindahkan keX-Original-*
, termasuk yang asliRemoteIpAddress/Host/Scheme/PathBase
.HttpContext.Request.Scheme
: AturX-Forwarded-Proto
menggunakan nilai header. Nilai yang digunakan dihapus dariX-Forwarded-Proto
, dan nilaiHttpContext.Request.Scheme
lama dipertahankan dalamX-Original-Proto
.HttpContext.Request.Host
: AturX-Forwarded-Host
menggunakan nilai header. Nilai yang digunakan dihapus dariX-Forwarded-Host
, dan nilaiHttpContext.Request.Host
lama dipertahankan dalamX-Original-Host
.HttpContext.Request.PathBase
: AturX-Forwarded-Prefix
menggunakan nilai header. Nilai yang digunakan dihapus dariX-Forwarded-Prefix
, dan nilaiHttpContext.Request.PathBase
lama dipertahankan dalamX-Original-Prefix
.
Untuk informasi selengkapnya tentang sebelumnya, lihat masalah GitHub ini.
Pengaturan default Middleware Header yang diteruskan dapat dikonfigurasi. Untuk pengaturan default:
- Hanya ada satu proksi antara aplikasi dan sumber permintaan.
- Hanya alamat loopback yang dikonfigurasi untuk proksi yang diketahui dan jaringan yang diketahui.
- Header yang diteruskan diberi nama
X-Forwarded-For
, ,X-Forwarded-Proto
X-Forwarded-Host
danX-Forwarded-Prefix
. - Nilainya
ForwardedHeaders
adalahForwardedHeaders.None
, penerus yang diinginkan harus diatur di sini untuk mengaktifkan middleware.
Tidak semua appliance jaringan menambahkan X-Forwarded-For
header dan X-Forwarded-Proto
tanpa konfigurasi tambahan. Lihat panduan produsen appliance Anda jika permintaan yang diproksi tidak berisi header ini saat mencapai aplikasi. Jika appliance menggunakan nama header yang berbeda dari X-Forwarded-For
dan X-Forwarded-Proto
, atur ForwardedForHeaderName opsi dan ForwardedProtoHeaderName agar sesuai dengan nama header yang digunakan oleh appliance. Untuk informasi selengkapnya, lihat Opsi Middleware Header yang Diteruskan dan Konfigurasi untuk proksi yang menggunakan nama header yang berbeda.
Modul IIS/IIS Express dan ASP.NET Core
Middleware Header yang Diteruskan diaktifkan secara default oleh IIS Integration Middleware ketika aplikasi dihosting di luar proses di belakang IIS dan ASP.NET Core Module (ANCM) untuk IIS. Middleware Header yang Diteruskan diaktifkan untuk dijalankan terlebih dahulu di alur middleware dengan konfigurasi terbatas khusus untuk Modul ASP.NET Core. Konfigurasi terbatas disebabkan oleh masalah kepercayaan dengan header yang diteruskan, misalnya, spoofing IP. Middleware dikonfigurasi untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
dan dibatasi untuk satu proksi localhost. Jika konfigurasi tambahan diperlukan, lihat opsi Middleware Header yang Diteruskan.
Skenario server proksi dan load balancer lainnya
Di luar penggunaan Integrasi IIS saat menghosting di luar proses, Middleware Header yang Diteruskan tidak diaktifkan secara default. Middleware Header yang Diteruskan harus diaktifkan agar aplikasi memproses header yang diteruskan dengan UseForwardedHeaders. Setelah mengaktifkan middleware jika tidak ForwardedHeadersOptions ditentukan ke middleware, ForwardedHeadersOptions.ForwardedHeaders default adalah ForwardedHeaders.None.
Konfigurasikan middleware dengan ForwardedHeadersOptions untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
.
Urutan Middleware Header yang Diteruskan
Middleware Header yang Diteruskan harus berjalan sebelum middleware lainnya. Urutan ini memastikan bahwa middleware yang mengandalkan informasi header yang diteruskan dapat menggunakan nilai header untuk pemrosesan. Middleware Header yang Diteruskan dapat berjalan setelah diagnostik dan penanganan kesalahan, tetapi harus dijalankan sebelum memanggil UseHsts:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Atau, panggil UseForwardedHeaders
sebelum diagnostik:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Catatan
Jika tidak ada ForwardedHeadersOptions yang ditentukan atau diterapkan langsung ke metode ekstensi dengan UseForwardedHeaders, header default yang akan diteruskan adalah ForwardedHeaders.None. Properti ForwardedHeaders harus dikonfigurasi dengan header untuk diteruskan.
Konfigurasi Nginx
Untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
, lihat Host ASP.NET Core di Linux dengan Nginx. Untuk informasi selengkapnya, lihat NGINX: Menggunakan header Yang Diteruskan.
Konfigurasi Apache
X-Forwarded-For
ditambahkan secara otomatis. Untuk informasi selengkapnya, lihat Modul Apache mod_proxy: Header Permintaan Proksi Terbalik.
Opsi Middleware Header yang Diteruskan
ForwardedHeadersOptions mengontrol perilaku Middleware Header yang Diteruskan. Contoh berikut mengubah nilai default:
- Membatasi jumlah entri dalam header yang diteruskan ke
2
. - Menambahkan alamat proksi yang diketahui dari
127.0.10.1
. - Mengubah nama header yang diteruskan dari default
X-Forwarded-For
keX-Forwarded-For-My-Custom-Header-Name
.
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Opsi | Deskripsi |
---|---|
AllowedHosts | Membatasi host menurut X-Forwarded-Host header ke nilai yang disediakan.
IList<string> . |
ForwardedForHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedForHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-For header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-For . |
ForwardedHeaders | Mengidentifikasi penerus mana yang harus diproses. Lihat Enum ForwardedHeaders untuk daftar bidang yang berlaku. Nilai umum yang ditetapkan ke properti ini adalah ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto .Nilai defaultnya adalah ForwardedHeaders.None. |
ForwardedHostHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedHostHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-Host header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-Host . |
ForwardedProtoHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedProtoHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-Proto header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-Proto . |
ForwardLimit | Membatasi jumlah entri dalam header yang diproses. Atur ke null untuk menonaktifkan batas, tetapi ini hanya boleh dilakukan jika KnownProxies atau KnownNetworks dikonfigurasi. Mengatur non-nilainull adalah tindakan pencegahan (tetapi bukan jaminan) untuk melindungi dari proksi yang salah dikonfigurasi dan permintaan berbahaya yang tiba dari saluran samping di jaringan.Middleware Header yang diteruskan memproses header dalam urutan terbalik dari kanan ke kiri. Jika nilai default ( 1 ) digunakan, hanya nilai paling kanan dari header yang diproses kecuali nilai ForwardLimit ditingkatkan.Default adalah 1 . |
KnownNetworks | Rentang alamat jaringan yang diketahui untuk menerima header yang diteruskan. Berikan rentang IP menggunakan notasi Classless Interdomain Routing (CIDR). Jika server menggunakan soket mode ganda, alamat IPv4 disediakan dalam format IPv6 (misalnya, 10.0.0.1 dalam IPv4 yang diwakili dalam IPv6 sebagai ::ffff:10.0.0.1 ). Lihat IPAddress.MapToIPv6. Tentukan apakah format ini diperlukan dengan melihat HttpContext.Connection.RemoteIpAddress.Defaultnya adalah berisi IList ><IPNetworksatu entri untuk .new IPNetwork(IPAddress.Loopback, 8) |
KnownProxies | Alamat proksi yang diketahui untuk menerima header yang diteruskan. Gunakan KnownProxies untuk menentukan kecocokan alamat IP yang tepat.Jika server menggunakan soket mode ganda, alamat IPv4 disediakan dalam format IPv6 (misalnya, 10.0.0.1 dalam IPv4 yang diwakili dalam IPv6 sebagai ::ffff:10.0.0.1 ). Lihat IPAddress.MapToIPv6. Tentukan apakah format ini diperlukan dengan melihat HttpContext.Connection.RemoteIpAddress.Defaultnya adalah berisi IList ><IPAddresssatu entri untuk .IPAddress.IPv6Loopback |
OriginalForHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalForHeaderName. Default adalah X-Original-For . |
OriginalHostHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalHostHeaderName. Default adalah X-Original-Host . |
OriginalProtoHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalProtoHeaderName. Default adalah X-Original-Proto . |
RequireHeaderSymmetry | Mengharuskan jumlah nilai header disinkronkan antara ForwardedHeadersOptions.ForwardedHeaders yang sedang diproses . Default dalam ASP.NET Core 1.x adalah true . Default dalam ASP.NET Core 2.0 atau yang lebih baru adalah false . |
Skenario dan kasus penggunaan
Ketika tidak dimungkinkan untuk menambahkan header yang diteruskan dan semua permintaan aman
Dalam beberapa kasus, mungkin tidak mungkin untuk menambahkan header yang diteruskan ke permintaan yang diproksikan ke aplikasi. Jika proksi memberlakukan bahwa semua permintaan eksternal publik adalah HTTPS, skema dapat diatur secara manual sebelum menggunakan semua jenis middleware:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Kode ini dapat dinonaktifkan dengan variabel lingkungan atau pengaturan konfigurasi lainnya dalam lingkungan pengembangan atau penahapan:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsProduction())
{
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
}
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Bekerja dengan basis jalur dan proksi yang mengubah jalur permintaan
Beberapa proksi melewati jalur secara utuh tetapi dengan jalur dasar aplikasi yang harus dihapus sehingga perutean berfungsi dengan baik. Middleware UsePathBaseExtensions.UsePathBase membagi jalur menjadi HttpRequest.Path dan jalur dasar aplikasi ke HttpRequest.PathBase.
Jika /foo
adalah jalur dasar aplikasi untuk jalur proksi yang diteruskan sebagai /foo/api/1
, middleware diatur Request.PathBase
ke /foo
dan Request.Path
ke /api/1
dengan perintah berikut:
app.UsePathBase("/foo");
// ...
app.UseRouting();
Catatan
Saat menggunakan WebApplication (lihat Migrasi dari ASP.NET Core 5.0 ke 6.0), app.UseRouting
harus dipanggil setelah UsePathBase
sehingga middleware perutean dapat mengamati jalur yang dimodifikasi sebelum mencocokkan rute. Jika tidak, rute dicocokkan sebelum jalur ditulis ulang oleh UsePathBase
seperti yang dijelaskan dalam artikel Pengurutan Middleware dan Perutean.
Jalur asli dan dasar jalur diterapkan kembali ketika middleware dipanggil lagi secara terbalik. Untuk informasi selengkapnya tentang pemrosesan pesanan middleware, lihat ASP.NET Core Middleware.
Jika proksi memangkas jalur (misalnya, meneruskan /foo/api/1
ke /api/1
), perbaiki pengalihan dan tautan dengan mengatur properti PathBase permintaan:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next(context);
});
Jika proksi menambahkan data jalur, buang bagian dari jalur untuk memperbaiki pengalihan dan tautan dengan menggunakan StartsWithSegments dan menetapkan ke Path properti:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next(context);
});
Konfigurasi untuk proksi yang menggunakan nama header yang berbeda
Jika proksi tidak menggunakan header bernama X-Forwarded-For
dan X-Forwarded-Proto
untuk meneruskan alamat/port proksi dan informasi skema asal, atur ForwardedForHeaderName opsi dan ForwardedProtoHeaderName agar sesuai dengan nama header yang digunakan oleh proksi:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "HeaderNamUsedByProxy_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "HeaderNamUsedByProxy_X-Forwarded-Proto_Header";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Meneruskan skema untuk proksi terbalik Linux dan non-IIS
Aplikasi yang memanggil UseHttpsRedirection dan UseHsts menempatkan situs ke dalam perulangan tak terbatas jika disebarkan ke Azure Linux App Service, komputer virtual (VM) Azure Linux, atau di belakang proksi terbalik lainnya selain IIS. TLS dihentikan oleh proksi terbalik, dan Kestrel tidak mengetahui skema permintaan yang benar. OAuth dan OIDC juga gagal dalam konfigurasi ini karena menghasilkan pengalihan yang salah. UseIISIntegration menambahkan dan mengonfigurasi Middleware Header yang Diteruskan saat berjalan di belakang IIS, tetapi tidak ada konfigurasi otomatis yang cocok untuk Linux (integrasi Apache atau Nginx).
Untuk meneruskan skema dari proksi dalam skenario non-IIS, aktifkan Middleware Header yang Diteruskan dengan mengatur ASPNETCORE_FORWARDEDHEADERS_ENABLED
ke true
. Peringatan: Bendera ini menggunakan pengaturan yang dirancang untuk lingkungan cloud dan tidak mengaktifkan fitur seperti KnownProxies option
untuk membatasi penerus IP mana yang diterima.
Penerusan sertifikat
Azure
Untuk mengonfigurasi Azure App Service untuk penerusan sertifikat, lihat Mengonfigurasi autentikasi bersama TLS untuk Azure App Service. Panduan berikut berkaitan dengan mengonfigurasi aplikasi ASP.NET Core.
- Konfigurasikan Middleware Penerusan Sertifikat untuk menentukan nama header yang digunakan Azure. Tambahkan kode berikut untuk mengonfigurasi header tempat middleware membangun sertifikat.
- Panggil UseCertificateForwarding sebelum panggilan ke UseAuthentication.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Proksi web lainnya
Jika proksi digunakan yang bukan IIS atau Perutean Permintaan Aplikasi (ARR) Azure App Service, konfigurasikan proksi untuk meneruskan sertifikat yang diterimanya di header HTTP.
- Konfigurasikan Middleware Penerusan Sertifikat untuk menentukan nama header. Tambahkan kode berikut untuk mengonfigurasi header tempat middleware membangun sertifikat.
- Panggil UseCertificateForwarding sebelum panggilan ke UseAuthentication.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Jika proksi tidak mengodekan sertifikat base64, seperti halnya dengan Nginx, atur HeaderConverter
opsi . Pertimbangkan contoh berikut:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
// Conversion logic to create an X509Certificate2.
var clientCertificate = ConversionLogic.CreateAnX509Certificate2();
return clientCertificate;
};
});
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
Pecahkan masalah
Ketika header tidak diteruskan seperti yang diharapkan, aktifkan debug
pengelogan tingkat dan pengelogan permintaan HTTP. UseHttpLogging harus dipanggil setelah UseForwardedHeaders:
using Microsoft.AspNetCore.HttpLogging;
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddHttpLogging(options =>
{
options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders;
});
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
// Connection: RemoteIp
app.Logger.LogInformation("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next(context);
});
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Jika ada beberapa nilai di header tertentu, Middleware Header yang Diteruskan memproses header dalam urutan terbalik dari kanan ke kiri. Defaultnya ForwardLimit
adalah 1
(satu), jadi hanya nilai paling kanan dari header yang diproses kecuali nilainya ForwardLimit
ditingkatkan.
IP jarak jauh asli permintaan harus cocok dengan entri dalam KnownProxies daftar atau KnownNetworks sebelum header yang diteruskan diproses. Ini membatasi spoofing header dengan tidak menerima penerus dari proksi yang tidak tepercaya. Ketika proksi yang tidak diketahui terdeteksi, pengelogan menunjukkan alamat proksi:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Dalam contoh sebelumnya, 10.0.0.100 adalah server proksi. Jika server adalah proksi tepercaya, tambahkan alamat IP server ke KnownProxies
, atau tambahkan jaringan tepercaya ke KnownNetworks
. Untuk informasi selengkapnya, lihat bagian Opsi Middleware Header yang Diteruskan.
using Microsoft.AspNetCore.HttpOverrides;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Untuk menampilkan log, tambahkan "Microsoft.AspNetCore.HttpLogging": "Information"
ke appsettings.Development.json
file:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging": "Information"
}
}
}
Penting
Hanya izinkan proksi dan jaringan tepercaya untuk meneruskan header. Jika tidak, serangan spoofing IP dimungkinkan .
Sumber Daya Tambahan:
Dalam konfigurasi yang direkomendasikan untuk ASP.NET Core, aplikasi dihosting menggunakan Modul IIS/ASP.NET Core, Nginx, atau Apache. Server proksi, load balancer, dan appliance jaringan lainnya sering mengaburkan informasi tentang permintaan sebelum mencapai aplikasi:
- Ketika permintaan HTTPS diproksi melalui HTTP, skema asli (HTTPS) hilang dan harus diteruskan di header.
- Karena aplikasi menerima permintaan dari proksi dan bukan sumber sebenarnya di Internet atau jaringan perusahaan, alamat IP klien asal juga harus diteruskan di header.
Informasi ini mungkin penting dalam pemrosesan permintaan, misalnya dalam pengalihan, autentikasi, pembuatan tautan, evaluasi kebijakan, dan geolokasi klien.
Header yang diteruskan
Menurut konvensi, proksi meneruskan informasi di header HTTP.
Header | Deskripsi |
---|---|
X-Forwarded-For | Menyimpan informasi tentang klien yang memulai permintaan dan proksi berikutnya dalam rantai proksi. Parameter ini mungkin berisi alamat IP (dan, secara opsional, nomor port). Dalam rantai server proksi, parameter pertama menunjukkan klien tempat permintaan pertama kali dibuat. Pengidentifikasi proksi berikutnya mengikuti. Proksi terakhir dalam rantai tidak ada dalam daftar parameter. Alamat IP proksi terakhir, dan secara opsional nomor port, tersedia sebagai alamat IP jarak jauh di lapisan transportasi. |
X-Forwarded-Proto | Nilai skema asal (HTTP/HTTPS). Nilai mungkin juga merupakan daftar skema jika permintaan telah melintasi beberapa proksi. |
X-Forwarded-Host | Nilai asli bidang header Host. Biasanya, proksi tidak mengubah header Host. Lihat Microsoft Security Advisory CVE-2018-0787 untuk informasi tentang kerentanan elevasi hak istimewa yang memengaruhi sistem di mana proksi tidak memvalidasi atau membatasi header Host ke nilai yang diketahui baik. |
Middleware Header yang Diteruskan (ForwardedHeadersMiddleware), membaca header ini dan mengisi bidang terkait pada HttpContext.
Pembaruan middleware:
- HttpContext.Connection.RemoteIpAddress: Atur
X-Forwarded-For
menggunakan nilai header. Pengaturan tambahan memengaruhi bagaimana middleware diaturRemoteIpAddress
. Untuk detailnya, lihat opsi Middleware Header yang Diteruskan. Nilai yang digunakan dihapus dariX-Forwarded-For
, dan nilai lama dipertahankan dalamX-Original-For
. Pola yang sama diterapkan ke header lain,Host
danProto
. - HttpContext.Request.Scheme: Atur
X-Forwarded-Proto
menggunakan nilai header. - HttpContext.Request.Host: Atur
X-Forwarded-Host
menggunakan nilai header.
Untuk informasi selengkapnya tentang sebelumnya, lihat masalah GitHub ini.
Pengaturan default Middleware Header yang diteruskan dapat dikonfigurasi. Untuk pengaturan default:
- Hanya ada satu proksi antara aplikasi dan sumber permintaan.
- Hanya alamat loopback yang dikonfigurasi untuk proksi yang diketahui dan jaringan yang diketahui.
- Header yang diteruskan diberi nama
X-Forwarded-For
danX-Forwarded-Proto
. - Nilainya
ForwardedHeaders
adalahForwardedHeaders.None
, penerus yang diinginkan harus diatur di sini untuk mengaktifkan middleware.
Tidak semua appliance jaringan menambahkan X-Forwarded-For
header dan X-Forwarded-Proto
tanpa konfigurasi tambahan. Lihat panduan produsen appliance Anda jika permintaan yang diproksi tidak berisi header ini saat mencapai aplikasi. Jika appliance menggunakan nama header yang berbeda dari X-Forwarded-For
dan X-Forwarded-Proto
, atur ForwardedForHeaderName opsi dan ForwardedProtoHeaderName agar sesuai dengan nama header yang digunakan oleh appliance. Untuk informasi selengkapnya, lihat Opsi Middleware Header yang Diteruskan dan Konfigurasi untuk proksi yang menggunakan nama header yang berbeda.
Modul IIS/IIS Express dan ASP.NET Core
Middleware Header yang Diteruskan diaktifkan secara default oleh IIS Integration Middleware saat aplikasi dihosting di luar proses di belakang IIS dan Modul Inti ASP.NET. Middleware Header yang Diteruskan diaktifkan untuk dijalankan terlebih dahulu di alur middleware dengan konfigurasi terbatas khusus untuk Modul inti ASP.NET karena masalah kepercayaan dengan header yang diteruskan (misalnya, spoofing IP). Middleware dikonfigurasi untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
dan dibatasi untuk satu proksi localhost. Jika konfigurasi tambahan diperlukan, lihat opsi Middleware Header yang Diteruskan.
Skenario server proksi dan load balancer lainnya
Di luar penggunaan Integrasi IIS saat menghosting di luar proses, Middleware Header yang Diteruskan tidak diaktifkan secara default. Middleware Header yang Diteruskan harus diaktifkan agar aplikasi memproses header yang diteruskan dengan UseForwardedHeaders. Setelah mengaktifkan middleware jika tidak ForwardedHeadersOptions ditentukan ke middleware, ForwardedHeadersOptions.ForwardedHeaders default adalah ForwardedHeaders.None.
Konfigurasikan middleware dengan ForwardedHeadersOptions untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
di Startup.ConfigureServices
.
Urutan Middleware Header yang Diteruskan
Middleware Header yang Diteruskan harus dijalankan sebelum middleware lainnya. Urutan ini memastikan bahwa middleware yang mengandalkan informasi header yang diteruskan dapat menggunakan nilai header untuk pemrosesan. Middleware Header yang Diteruskan dapat berjalan setelah diagnostik dan penanganan kesalahan, tetapi harus dijalankan sebelum memanggil UseHsts
:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Atau, panggil UseForwardedHeaders
sebelum diagnostik:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Catatan
Jika tidak ada ForwardedHeadersOptions yang ditentukan dalam Startup.ConfigureServices
atau langsung ke metode ekstensi dengan UseForwardedHeaders, header default yang akan diteruskan adalah ForwardedHeaders.None. Properti ForwardedHeaders harus dikonfigurasi dengan header untuk diteruskan.
Konfigurasi Nginx
Untuk meneruskan X-Forwarded-For
header dan X-Forwarded-Proto
, lihat Host ASP.NET Core di Linux dengan Nginx. Untuk informasi selengkapnya, lihat NGINX: Menggunakan header Yang Diteruskan.
Konfigurasi Apache
X-Forwarded-For
ditambahkan secara otomatis (lihat Modul Apache mod_proxy: Header Permintaan Proksi Terbalik).
Opsi Middleware Header yang Diteruskan
ForwardedHeadersOptions mengontrol perilaku Middleware Header yang Diteruskan. Contoh berikut mengubah nilai default:
- Batasi jumlah entri di header yang diteruskan ke
2
. - Tambahkan alamat proksi yang diketahui dari
127.0.10.1
. - Ubah nama header yang diteruskan dari default
X-Forwarded-For
menjadiX-Forwarded-For-My-Custom-Header-Name
.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
Opsi | Deskripsi |
---|---|
AllowedHosts | Membatasi host menurut X-Forwarded-Host header ke nilai yang disediakan.
IList<string> . |
ForwardedHeaders | Mengidentifikasi penerus mana yang harus diproses. Lihat Enum ForwardedHeaders untuk daftar bidang yang berlaku. Nilai umum yang ditetapkan ke properti ini adalah ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto .Nilai defaultnya adalah ForwardedHeaders.None. |
ForwardedForHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedForHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-For header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-For . |
ForwardedHostHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedHostHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-Host header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-Host . |
ForwardedProtoHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedProtoHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-Proto header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-Proto . |
ForwardedPrefixHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XForwardedPrefixHeaderName. Opsi ini digunakan ketika proksi/penerus tidak menggunakan X-Forwarded-Prefix header tetapi menggunakan beberapa header lain untuk meneruskan informasi.Default adalah X-Forwarded-Prefix . |
ForwardLimit | Membatasi jumlah entri dalam header yang diproses. Atur ke null untuk menonaktifkan batas, tetapi ini hanya boleh dilakukan jika KnownProxies atau KnownNetworks dikonfigurasi. Mengatur non-nilainull adalah tindakan pencegahan (tetapi bukan jaminan) untuk melindungi dari proksi yang salah dikonfigurasi dan permintaan berbahaya yang tiba dari saluran samping di jaringan.Middleware Header yang diteruskan memproses header dalam urutan terbalik dari kanan ke kiri. Jika nilai default ( 1 ) digunakan, hanya nilai paling kanan dari header yang diproses kecuali nilai ForwardLimit ditingkatkan.Default adalah 1 . |
KnownNetworks | Rentang alamat jaringan yang diketahui untuk menerima header yang diteruskan. Berikan rentang IP menggunakan notasi Classless Interdomain Routing (CIDR). Jika server menggunakan soket mode ganda, alamat IPv4 disediakan dalam format IPv6 (misalnya, 10.0.0.1 dalam IPv4 yang diwakili dalam IPv6 sebagai ::ffff:10.0.0.1 ). Lihat IPAddress.MapToIPv6. Tentukan apakah format ini diperlukan dengan melihat HttpContext.Connection.RemoteIpAddress.Defaultnya adalah berisi IList ><IPNetworksatu entri untuk .new IPNetwork(IPAddress.Loopback, 8) |
KnownProxies | Alamat proksi yang diketahui untuk menerima header yang diteruskan. Gunakan KnownProxies untuk menentukan kecocokan alamat IP yang tepat.Jika server menggunakan soket mode ganda, alamat IPv4 disediakan dalam format IPv6 (misalnya, 10.0.0.1 dalam IPv4 yang diwakili dalam IPv6 sebagai ::ffff:10.0.0.1 ). Lihat IPAddress.MapToIPv6. Tentukan apakah format ini diperlukan dengan melihat HttpContext.Connection.RemoteIpAddress.Defaultnya adalah berisi IList ><IPAddresssatu entri untuk .IPAddress.IPv6Loopback |
OriginalForHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalForHeaderName. Default adalah X-Original-For . |
OriginalHostHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalHostHeaderName. Default adalah X-Original-Host . |
OriginalProtoHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalProtoHeaderName. Default adalah X-Original-Proto . |
OriginalPrefixHeaderName | Gunakan header yang ditentukan oleh properti ini alih-alih yang ditentukan oleh ForwardedHeadersDefaults.XOriginalPrefixHeaderName. Default adalah X-Original-Prefix . |
RequireHeaderSymmetry | Mengharuskan jumlah nilai header disinkronkan antara ForwardedHeadersOptions.ForwardedHeaders yang sedang diproses . Default dalam ASP.NET Core 1.x adalah true . Default dalam ASP.NET Core 2.0 atau yang lebih baru adalah false . |
Skenario dan kasus penggunaan
Ketika tidak dimungkinkan untuk menambahkan header yang diteruskan dan semua permintaan aman
Dalam beberapa kasus, mungkin tidak mungkin untuk menambahkan header yang diteruskan ke permintaan yang diproksikan ke aplikasi. Jika proksi memberlakukan bahwa semua permintaan eksternal publik adalah HTTPS, skema dapat diatur Startup.Configure
secara manual sebelum menggunakan semua jenis middleware:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
Kode ini dapat dinonaktifkan dengan variabel lingkungan atau pengaturan konfigurasi lainnya dalam lingkungan pengembangan atau penahapan.
Menangani basis jalur dan proksi yang mengubah jalur permintaan
Beberapa proksi melewati jalur secara utuh tetapi dengan jalur dasar aplikasi yang harus dihapus sehingga perutean berfungsi dengan baik. Middleware UsePathBaseExtensions.UsePathBase membagi jalur menjadi HttpRequest.Path dan jalur dasar aplikasi ke HttpRequest.PathBase.
Jika /foo
adalah jalur dasar aplikasi untuk jalur proksi yang diteruskan sebagai /foo/api/1
, middleware diatur Request.PathBase
ke /foo
dan Request.Path
ke /api/1
dengan perintah berikut:
app.UsePathBase("/foo");
Jalur asli dan dasar jalur diterapkan kembali ketika middleware dipanggil lagi secara terbalik. Untuk informasi selengkapnya tentang pemrosesan pesanan middleware, lihat ASP.NET Core Middleware.
Jika proksi memangkas jalur (misalnya, meneruskan /foo/api/1
ke /api/1
), perbaiki pengalihan dan tautan dengan mengatur properti PathBase permintaan:
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next();
});
Jika proksi menambahkan data jalur, buang bagian dari jalur untuk memperbaiki pengalihan dan tautan dengan menggunakan StartsWithSegments dan menetapkan ke Path properti:
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next();
});
Konfigurasi untuk proksi yang menggunakan nama header yang berbeda
Jika proksi tidak menggunakan header bernama X-Forwarded-For
dan X-Forwarded-Proto
untuk meneruskan alamat/port proksi dan informasi skema asal, atur ForwardedForHeaderName opsi dan ForwardedProtoHeaderName agar sesuai dengan nama header yang digunakan oleh proksi:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});
Meneruskan skema untuk proksi terbalik Linux dan non-IIS
Aplikasi yang memanggil UseHttpsRedirection dan UseHsts menempatkan situs ke dalam perulangan tak terbatas jika disebarkan ke Azure Linux App Service, komputer virtual (VM) Azure Linux, atau di belakang proksi terbalik lainnya selain IIS. TLS dihentikan oleh proksi terbalik, dan Kestrel tidak mengetahui skema permintaan yang benar. OAuth dan OIDC juga gagal dalam konfigurasi ini karena menghasilkan pengalihan yang salah. UseIISIntegration menambahkan dan mengonfigurasi Middleware Header yang Diteruskan saat berjalan di belakang IIS, tetapi tidak ada konfigurasi otomatis yang cocok untuk Linux (integrasi Apache atau Nginx).
Untuk meneruskan skema dari proksi dalam skenario non-IIS, tambahkan dan konfigurasikan Middleware Header yang Diteruskan. Di Startup.ConfigureServices
, gunakan kode berikut:
// using Microsoft.AspNetCore.HttpOverrides;
if (string.Equals(
Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"),
"true", StringComparison.OrdinalIgnoreCase))
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
// Only loopback proxies are allowed by default.
// Clear that restriction because forwarders are enabled by explicit
// configuration.
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
}
Penerusan sertifikat
Azure
Untuk mengonfigurasi Azure App Service untuk penerusan sertifikat, lihat Mengonfigurasi autentikasi bersama TLS untuk Azure App Service. Panduan berikut berkaitan dengan mengonfigurasi aplikasi ASP.NET Core.
Di Startup.Configure
, tambahkan kode berikut sebelum panggilan ke app.UseAuthentication();
:
app.UseCertificateForwarding();
Konfigurasikan Middleware Penerusan Sertifikat untuk menentukan nama header yang digunakan Azure. Di Startup.ConfigureServices
, tambahkan kode berikut untuk mengonfigurasi header tempat middleware membangun sertifikat:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
Proksi web lainnya
Jika proksi digunakan yang bukan IIS atau Perutean Permintaan Aplikasi (ARR) Azure App Service, konfigurasikan proksi untuk meneruskan sertifikat yang diterimanya di header HTTP. Di Startup.Configure
, tambahkan kode berikut sebelum panggilan ke app.UseAuthentication();
:
app.UseCertificateForwarding();
Konfigurasikan Middleware Penerusan Sertifikat untuk menentukan nama header. Di Startup.ConfigureServices
, tambahkan kode berikut untuk mengonfigurasi header tempat middleware membangun sertifikat:
services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
Jika proksi tidak mengodekan sertifikat base64 (seperti halnya dengan Nginx), atur HeaderConverter
opsi . Pertimbangkan contoh berikut di Startup.ConfigureServices
:
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
var clientCertificate =
/* some conversion logic to create an X509Certificate2 */
return clientCertificate;
}
});
Pecahkan masalah
Saat header tidak diteruskan seperti yang diharapkan, aktifkan pengelogan. Jika log tidak memberikan informasi yang memadai untuk memecahkan masalah, hitung header permintaan yang diterima oleh server. Gunakan middleware sebaris untuk menulis header permintaan ke respons aplikasi atau mencatat header.
Untuk menulis header ke respons aplikasi, letakkan middleware sebaris terminal berikut segera setelah panggilan ke UseForwardedHeaders di Startup.Configure
:
app.Run(async (context) =>
{
context.Response.ContentType = "text/plain";
// Request method, scheme, and path
await context.Response.WriteAsync(
$"Request Method: {context.Request.Method}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Scheme: {context.Request.Scheme}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Path: {context.Request.Path}{Environment.NewLine}");
// Headers
await context.Response.WriteAsync($"Request Headers:{Environment.NewLine}");
foreach (var header in context.Request.Headers)
{
await context.Response.WriteAsync($"{header.Key}: " +
$"{header.Value}{Environment.NewLine}");
}
await context.Response.WriteAsync(Environment.NewLine);
// Connection: RemoteIp
await context.Response.WriteAsync(
$"Request RemoteIp: {context.Connection.RemoteIpAddress}");
});
Anda dapat menulis ke log alih-alih isi respons. Menulis ke log memungkinkan situs berfungsi secara normal saat penelusuran kesalahan.
Untuk menulis log daripada ke isi respons:
ILogger<Startup>
Masukkan ke kelas seperti yangStartup
dijelaskan dalam Membuat log di Startup.- Tempatkan middleware sebaris berikut segera setelah panggilan ke UseForwardedHeaders di
Startup.Configure
.
app.Use(async (context, next) =>
{
// Request method, scheme, path, and base path
_logger.LogDebug("Request Method: {Method}", context.Request.Method);
_logger.LogDebug("Request Scheme: {Scheme}", context.Request.Scheme);
_logger.LogDebug("Request Path: {Path}", context.Request.Path);
_logger.LogDebug("Request Path Base: {PathBase}", context.Request.PathBase);
// Headers
foreach (var header in context.Request.Headers)
{
_logger.LogDebug("Header: {Key}: {Value}", header.Key, header.Value);
}
// Connection: RemoteIp
_logger.LogDebug("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next();
});
Saat diproses, X-Forwarded-{For|Proto|Host|Prefix}
nilai dipindahkan ke X-Original-{For|Proto|Host|Prefix}
. Jika ada beberapa nilai di header tertentu, Middleware Header yang Diteruskan memproses header dalam urutan terbalik dari kanan ke kiri. Defaultnya ForwardLimit
adalah 1
(satu), jadi hanya nilai paling kanan dari header yang diproses kecuali nilainya ForwardLimit
ditingkatkan.
IP jarak jauh asli permintaan harus cocok dengan entri dalam KnownProxies
daftar atau KnownNetworks
sebelum header yang diteruskan diproses. Ini membatasi spoofing header dengan tidak menerima penerus dari proksi yang tidak tepercaya. Ketika proksi yang tidak diketahui terdeteksi, pengelogan menunjukkan alamat proksi:
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
Dalam contoh sebelumnya, 10.0.0.100 adalah server proksi. Jika server adalah proksi tepercaya, tambahkan alamat IP server ke KnownProxies
(atau tambahkan jaringan tepercaya ke KnownNetworks
) di Startup.ConfigureServices
. Untuk informasi selengkapnya, lihat bagian Opsi Middleware Header yang Diteruskan.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
Penting
Hanya izinkan proksi dan jaringan tepercaya untuk meneruskan header. Jika tidak, serangan spoofing IP dimungkinkan .
Sumber Daya Tambahan:
ASP.NET Core