NTLMを使用するWindows認証でリバースプロキシを実行できるかどうか誰でも知っていますか?これに関する例は見つかりません。 more_set_headersフィールドの値は何ですか?
location / {
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_set_header Host $Host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
more_set_input_headers 'Authorization: $http_authorization';
proxy_set_header Accept-Encoding "";
proxy_pass http://Host/;
proxy_redirect default;
#This is what worked for me, but you need the headers-more mod
more_set_headers -s 401 'WWW-Authenticate: Basic realm="Host.local"';
}
ホストに直接アクセスした場合、リバースプロキシでアクセスした場合、認証は毎回失敗します。
NginxでNTLMパススルーを有効にするには-
upstream http_backend {
server 2.3.4.5:80;
keepalive 16;
}
server {
...
location / {
proxy_pass http://http_backend/;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
- ラモン
私の知る限り、これは現在nginxでは不可能です。少し前に自分で詳しく調べました。基本的な問題は、NTLM認証では後続のリクエストで同じソケットを使用する必要があるが、プロキシはそれを行わないことです。 nginx開発チームがこの動作に何らかのサポートを提供するまで、これを処理する方法は、リバースプロキシ自体で認証を使用することでした。私は現在、Apache 2.2、mod_proxy、mod_auth_sspiを使用してこれを行っています(完璧ではありませんが、動作します)。幸運を!申し訳ありません、nginx、私はあなたを愛していますが、私たちは本当にこの一般的なユースケースのためにいくつかの助けを使うことができました。
それ以来、私はこのための別の解決策を考え出しました。これは、NTLMを実行するnginxと同じではありません(nginxチームがこれを実装する場合、これは素晴らしいことです)。しかし、今のところ、私がやっていることは私たちにとってうまくいきます。
暗号化されたcookieを使用するluaコードをいくつか作成しました。暗号化されたCookieには、ユーザーのID、ユーザーが認証された時間、ユーザーが認証に使用したIPアドレスが含まれます。参考のためにここに添付します。洗練されていませんが、おそらく、それを使用して独自の同様のスキームを開発できます。
基本的に、それがどのように機能するかです:
access.lua:
local enc = require("enc");
local strings = require("strings");
local dkjson = require("dkjson");
function beginAuth()
local headers = ngx.req.get_headers();
local contentTypeOriginal = headers["Content-Type"];
print( contentTypeOriginal );
ngx.req.set_header( "Content-Type", "application/json" );
local method = ngx.req.get_method();
local body = "";
if method == "POST" then
local requestedWith = headers["X-Requested-With"];
if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
print( "bailing, won't allow post during re-authentication." );
ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication. user must do a get first. cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
ngx.say("Reload the page.");
return;
else
print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
end
ngx.req.read_body();
local bodyData = ngx.req.get_body_data();
if bodyData ~= nil then
body = bodyData;
end
end
local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
local origData = enc.base64encode( json );
local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.Host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
if contentTypeOriginal ~= nil then
ngx.req.set_header( "Content-Type", contentTypeOriginal );
else
ngx.req.clear_header( "Content-Type" );
end
if res.status == 200 then
ngx.header["Access-Control-Allow-Origin"] = "*";
ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
else
ngx.exit(res.status);
end
end
function completeAuth( cookie )
local guid = enc.decrypt( string.sub( cookie, 6 ) );
local contentTypeOriginal = ngx.header["Content-Type"];
ngx.req.set_header( "Content-Type", "application/json" );
local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
if contentTypeOriginal ~= nil then
ngx.req.set_header( "Content-Type", contentTypeOriginal );
else
ngx.req.clear_header( "Content-Type" );
end
if res.status == 200 then
local resJson = res.body;
-- print( "here a1" );
-- print( resJson );
local resTbl = dkjson.decode( resJson );
if resTbl.StatusCode == 0 then
resTbl = resTbl.Result;
local time = os.time();
local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
ngx.req.set_header( "REMOTE_USER", resTbl.user );
if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
local tblJson = enc.base64decode( resTbl.originalData );
local tbl = dkjson.decode( tblJson );
if tbl.m ~= nil and tbl.m == "POST" then
ngx.req.set_method( ngx.HTTP_POST );
ngx.req.set_header( "Content-Type", tbl.c );
ngx.req.read_body();
ngx.req.set_body_data( tbl.d );
end
end
else
ngx.log( ngx.ERR, "error parsing json " .. resJson );
ngx.exit(500);
end
else
print( "error completing auth." );
ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
print( res.status );
ngx.exit(res.status);
end
end
local cookie = ngx.var.cookie_pca;
print( cookie );
if cookie == nil then
beginAuth();
elseif strings.starts( cookie, "guid:" ) then
completeAuth( cookie );
else
-- GOOD TO GO...
local json = enc.decrypt( cookie );
local d = dkjson.decode( json );
local now = os.time();
local diff = now - d.t;
local diffOriginal = 0;
if d.o ~= nil then
diffOriginal = now - d.o;
end
if diff > 3600 or diffOriginal > 43200 then
beginAuth();
elseif diff > 300 then
print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
end
ngx.req.set_header( "REMOTE_USER", d.u );
end
strings.lua:
local private = {};
local public = {};
strings = public;
function public.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function public.ends(String,End)
return End=='' or string.sub(String,-string.len(End))==End
end
return strings;
enc.lua:
-- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
local private = {};
local public = {};
enc = public;
local aeslua = require("aeslua");
private.key = "f8d7shfkdjfhhggf";
function public.encrypt( s )
return base64.base64encode( aeslua.encrypt( private.key, s ) );
end
function public.decrypt( s )
return aeslua.decrypt( private.key, base64.base64decode( s ) );
end
return enc;
サンプルnginx conf:
upstream dev {
ip_hash;
server app.server.local:8080;
}
set $authurl http://auth.server.local:8082/root/;
set $FrontEndProtocol https://;
location / {
proxy_pass http://dev/;
proxy_set_header Host $Host;
proxy_redirect default;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_buffers 128 8k;
access_by_lua_file conf/lua/app/dev/access.lua;
}
わかりました、私達はnginx/openrestyのために lua code を書きました、それはいくつかの解決可能な制限と商業のnginxバージョンの必要なしでntlm逆プロキシ問題を解決します