我有個 IIS 網站同時繫結多個 IP,想做到依據連上的伺服器 IP 授與不同權限,例如: 有些功能開放外網 IP 連入使用,某些功能限定內網及 localhost IP 才能用。設立兩個站台繫結不同 IP 及 Port 但共用同一份 ASP.NET 程式碼是一種解法,但我貪圖共用 Process 及靜態物件的便利性,因此要研究正確識別 Request 伺服器來源 IP 的方法。

舉最簡單的例子,IIS 預設繫結到所有 IP 位址("*"),而若伺服器 IP 為 172.28.1.1,則使用者用 httq://127.0.0.1、httq://localhost、httq://172.28.1.1 連上的都是同一站台。

如果不花腦筋,Request.Url.Host 會依瀏覽器輸入的 URL 分別傳回 127.0.0.1、localhost、172.28.1.1,似乎可用。但仔細想想不對! Host 資訊由 Request 內容決定,可能會被偽造,萬萬不可做為資安或權限管控依據。

查了文件,IIS 提供的 ServerVariables 變數裡有個 LOCAL_ADDR:

Returns the server address on which the request came in. This is important on computers where there can be multiple IP addresses bound to the computer, and you want to find out which address the request used.

LOCAL_ADDR 位址由 IIS 決定,是較可靠的來源。

我寫了以下程式實測:

    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return Content($@"
Url.Host={Request.Url.Host},
LOCAL_ADDR={Request.ServerVariables["LOCAL_ADDR"]}");
        }
    }

使用瀏覽器測試,Url.Host 與 LOCAL_ADDR 都會依網址傳回不同結果,足以區別使用者連上的伺服器 IP:

不過,瀏覽器測試 OK 不代表不能做壞事,花一點點功夫寫幾行程式(註: 用 curl 工具甚至連程式都不必寫),靠著偽造 Host Header 輕鬆騙過 Rquest.Url.Host,想指定為任何字串都成:

經以上實驗證明,Request.Url.Host 不可信,不建議用於安全管控,ServerVariables LOCAL_ADDR、SERVER_PORT 是較好的選擇。


Comments

Be the first to post a comment

Post a comment