PG14:auth_delay 外掛原始碼分析

ZARD_Fans發表於2024-03-14

auth_delay 讓伺服器在報告身份驗證失敗前短暫暫停,以增加對資料庫密碼進行暴力破解的難度。需要注意的是,這對阻止拒絕服務攻擊毫無幫助,甚至可能加劇攻擊,因為在報告身份驗證失敗前等待的程序仍會佔用連線。

要使用這個模組必須要在 postgresql.conf 中配置引數

shared_preload_libraries = 'auth_delay'
auth_delay.milliseconds = '500'

這個程式碼比較簡單,一共分為三個部分。

  1. hook 函式

在 libpq 中定義了一個 ClientAuthentication_hook 函式指標,程式碼如下:

typedef void (*ClientAuthentication_hook_type) (Port *, int);

/*
 * This hook allows plugins to get control following client authentication,
 * but before the user has been informed about the results.  It could be used
 * to record login events, insert a delay after failed authentication, etc.
 */
ClientAuthentication_hook_type ClientAuthentication_hook = NULL;

  1. _PG_init 函式
void
_PG_init(void)
{
	/* Define custom GUC variables */
	DefineCustomIntVariable("auth_delay.milliseconds",
							"Milliseconds to delay before reporting authentication failure",
							NULL,
							&auth_delay_milliseconds,
							0,
							0, INT_MAX / 1000,
							PGC_SIGHUP,
							GUC_UNIT_MS,
							NULL,
							NULL,
							NULL);
	/* Install Hooks */
	original_client_auth_hook = ClientAuthentication_hook;
	ClientAuthentication_hook = auth_delay_checks;
}

這個 _PG_init 函式會在模組呼叫之前執行,這個函式主要實現的功能是定義了一個 GUC 引數 auth_delay.milliseconds 這個引數我們需要在 postgresql.conf 中進行配置,然後它將原來的鉤子函式儲存在了 original_client_auth_hook 變數中,然後將我們自己的 auth_delay_checks 函式賦給了 ClientAuthentication_hook 變數,這樣我們就可以讓資料庫呼叫我們的函式了。

  1. auth_delay_checks 函式
static void
auth_delay_checks(Port *port, int status)
{
	/*
	 * Any other plugins which use ClientAuthentication_hook.
	 */
	if (original_client_auth_hook)
		original_client_auth_hook(port, status);

	/*
	 * Inject a short delay if authentication failed.
	 */
	if (status != STATUS_OK)
	{
		pg_usleep(1000L * auth_delay_milliseconds);
	}
}

這個函式的意思是如果原來存在有鉤子函式就先執行原來的鉤子函式,然後我們看一下驗證的狀態 status 是不是正確,如果不正確,就延時 auth_delay_milliseconds 個時間。

相關文章