天天看點

centos iptables_等保測評:Centos逾時退出詳解

一、說明

等保測評主機測評中需要查詢主機的逾時退出配置,具體在Centos中的話,主要有兩種方式可以實作逾時退出的功能。其實這方面的資料很多,但是仍然存在一些地方沒有說清楚(sshd_config的一個參數),是以本文的目的之一就是把那些問題說清楚。

注:我使用的是Centos6

另外本文也順便說一說在linux系統中,查詢配置的一個注意點。

二、設定TMOUT方式

這個是比較通用、簡單的方式,通過設定TMOUT,就可以至少對本地tty登入和遠端使用ssh登入的使用者起作用,但應該對圖形化界面無效,當然進入圖形化界面你再打開終端,對于打開的終端也是起作用的。

2.1. 實作方式

在/etc/profile、~/.bashrc、~/.bash_profile等檔案的最後加入export TMOUT=900語句即可(機關是秒),然後想要不重新登入就起效就,還需要用source指令解析上述檔案。

上述檔案中,/etc/profile針對所有使用者其效果,而~/.bashrc、~/.bash_profile則隻對目前使用者其效果,實際上從檔案位置就能看出來。

2.2. 具體查詢方式

從上面可以知道,理論上可以在好幾個地方對TMOUT進行配置,不過一般應該是在/etc/profile這個檔案中對所有使用者進行設定,可能有極個别的會單獨為每個使用者配置逾時時間。

是以直接檢視/etc/profile檔案内容,然後再用echo $TMOUT語句看看運作環境中的TMOUT變量到底是多少。

2.3. 配置查詢的注意點

這裡多說一點,在查配置時,對于linux系統最好是配置檔案以及實際情況一塊查。

為什麼要一塊查?

因為配置檔案裡寫了不代表就起效了,比如/etc/profile修改後需要用source指令才能起效。另外,配置檔案中的配置即使起效了,但未必就等同于現在實際執行的規則。

比如iptables的規則可以用指令動态修改,當然如果沒有使用指令持久化(也就是将目前規則存入iptables的配置檔案中)的話,重新開機iptables服務那些臨時的規則就沒了。

是以同樣的,配置檔案裡啥都沒寫,不代表現在運作的環境中沒有規則,比如iptables的規則可以用指令臨時添加進來。

是以如果想在測評的時候更全面的了解情況,最好就是一塊查。

三、修改sshd_config檔案方式

一般來說,遠端對linux伺服器進行管理都是通過ssh協定,是以對sshd_config檔案進行配置,也是一種方法,雖然隻對通過ssh登入的所有使用者有效。

記住修改完sshd_config檔案後需要重新開機才能生效。

在sshd_config檔案中有兩個參數,分别是ClientAliveInterval和ClientAliveCountMax。

這裡網上好像沒說清楚,這裡根據ClientAliveCountMax的取值是不是0,會有兩種效果。

3.1. ClientAliveCountMax的值是0

這種情況下,就是我們想要的操作逾時自動退出的效果,也就是當用戶端多久沒有操作,伺服器端就直接斷開ssh連接配接。

這個“多久”當然就是由ClientAliveInterval的值來決定,它的機關是秒。

比如ClientAliveInterval是600,ClientAliveCountMax是0,則代表着如果600秒内終端沒有操作,則斷開ssh連接配接。

3.2. ClientAliveCountMax的值大于0

這種情況下,和我們想要的效果有差別:

ClientAliveInterval:指定了伺服器端向用戶端請求消息的時間間隔,預設值是0;

ClientAliveCountMax:則指定這種請求伺服器端發送後,用戶端最多的無響應次數(但網上一般是說伺服器端最多向用戶端發送這種消息多少次,我覺得不太對),預設值是3。

如果ClientAliveInterval是60,ClientAliveCountMax是1,表面上看它的意思就是如果60s内用戶端沒有響應,伺服器端就會給用戶端發送一個請求判斷還它存不存在,如果1次也就是60秒都沒有任何回複,就斷開連接配接。

是以咋一看上去,和ClientAliveCountMax的值是0時沒啥差別,還是60秒後不操作就自動斷開不了啊。

但實際上壓根不一樣,因為當伺服器端給用戶端發送一個請求判斷還它存不存在時,用戶端應該是會自動回複的,同時,ClientAliveCountMax并不是指會發送這種消息多少次,或者好像和這個壓根就沒關系,它應該是指伺服器端發送這種請求後,用戶端最多的無響應次數,而且還得是連續的,因為從源代碼裡面看(見下文),隻要有一次正常相應,這個次數就會被清空。

也就是說,這裡判斷的應該是用戶端那邊網絡有沒有出現問題,比如斷線了之類的。

因為隻要網絡正常,用戶端這邊永遠會自動回複伺服器端發送過來的請求,則這個計數永遠達不到限定的門檻值1,也永遠不會自動退出(理想情況下啊),和你有沒有進行操作沒有任何關系……

我自己測試過,将ClientAliveInterval設定為60,ClientAliveCountMax設定1,然後我一直不操作,同時我把xshell裡保持活動狀态的選項關掉:

centos iptables_等保測評:Centos逾時退出詳解

結果就是到了60秒後根本不會自動退出……

然後我又把ClientAliveInterval和ClientAliveCountMax都設定成1,結果就是伺服器那邊每隔1秒就發個消息過來(有消息傳輸的時候那個箭頭會亮):

centos iptables_等保測評:Centos逾時退出詳解

要是按照網上的解釋,最多隻發送1次這種消息就結束會話,那壓根解釋不通,這都給我發了無數次了……

我跑去看man裡的解釋,也沒看出是以然:

ClientAliveCountMax             Sets the number of client alive messages (see below) which may be sent without sshd(8) receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session. It is important to note that the use of client alive messages is very different from TCPKeepAlive (below). The client alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by TCPKeepAlive is spoofable.  The client alive mechanism is valuable when the client or server depend on knowing when a connection has become inactive. The default value is 3\. If ClientAliveInterval (see below) is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. This option applies to protocol version 2 only.ClientAliveInterval          Sets a timeout interval in seconds after which if no data has been received from the client, sshd(8) will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client. This option applies to protocol version 2 only.
           

3.3. 源代碼解釋

于是我就去翻了翻源代碼,不過我對c語言不熟,隻能大概猜一猜了(有錯誤請見諒):

wait_until_can_do_something函數裡有這麼一段:

/* Wait for something to happen, or the timeout to expire. */    ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);    if (ret == -1) {        memset(*readsetp, 0, *nallocp);        memset(*writesetp, 0, *nallocp);        if (errno != EINTR)            error("select: %.100s", strerror(errno));    } else {        if (ret == 0 && client_alive_scheduled)            client_alive_check();        if (!compat20 && program_alive_scheduled && fdin_is_tty) {            if (!fdout_eof)                FD_SET(fdout, *readsetp);            if (!fderr_eof)                FD_SET(fderr, *readsetp);        }    }
           

裡面的select函數定義是這樣的:

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*timeout);
           

它能夠監視我們需要監視的檔案描述符的變化情況——讀寫或是異常,它的最後一個參數timeval*timeout是一個逾時時間,如果timeout的值大于0,這就是等待的逾時時間,即select在timeout時間内阻塞,逾時時間之内有事件到來就傳回了,否則在逾時後不管怎樣一定傳回。

如果timeout的值是null,則代表将select置于阻塞狀态,一定等到監視檔案描述符集合中某個檔案描述符發生變化為止。

而傳回值為-1代表出異常了,為0則代表逾時時間内,監視的這些檔案即沒有可寫的也沒有可讀的,換句話說,為0就是意味着用戶端那沒有任何操作。

在代碼中,在一定的條件下,這個timeout的值就是我們設定的ClientAliveInterval的值(如果設定值大于0),如果ClientAliveInterval是0,則timeout的值根據一些條件則為null。

然後根據client_alive_scheduled的值,就有可能調用client_alive_check(),不過如果是使用ssh2協定然後設定了ClientAliveInterval,應該client_alive_scheduled的值就是1,代碼如下:

if (compat20 &&        max_time_milliseconds == 0 && options.client_alive_interval) {        client_alive_scheduled = 1;        max_time_milliseconds = options.client_alive_interval * 1000;    }
           

client_alive_check的定義如下:

static voidclient_alive_check(void){    int channel_id;    /* timeout, check to see how many we have had */    if (packet_inc_alive_timeouts() > options.client_alive_count_max) {        logit("Timeout, client not responding.");        cleanup_exit(255);    }    /*     * send a bogus global/channel request with "wantreply",     * we should get back a failure     */    if ((channel_id = channel_find_open()) == -1) {        packet_start(SSH2_MSG_GLOBAL_REQUEST);        packet_put_cstring("[email protected]");        packet_put_char(1);    /* boolean: want reply */    } else {        channel_request_start(channel_id, "[email protected]", 1);    }    packet_send();}
           

可以看到如果packet_inc_alive_timeouts()大于options.client_alive_count_max,則就結束了。

而packet_inc_alive_timeouts的定義很簡單,就是把累積的timeouts

加個1,然後傳回。

intpacket_inc_alive_timeouts(void){    return ++active_state->keep_alive_timeouts;}
           

是以,如果設定的ClientAliveCountMax是0,到這裡就直接結束了(0+1>0),不會執行下面的發送請求的代碼。

如果(channel_id = channel_find_open())不為-1,應該代表channel沒問題的話,就會執行:

channel_request_start(channel_id, "[email protected]", 1);
           

channel_request_start中有這麼一句:

packet_start(SSH2_MSG_CHANNEL_REQUEST);
           

而SSH2_MSG_CHANNEL_REQUEST應該是綁定了一個函數

dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
           

是以就會調用server_input_channel_req函數,server_input_channel_req函數在有這麼一段:

reply = packet_get_char();…………if (reply) {        packet_start(success ?            SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);        packet_put_int(c->remote_id);        packet_send();    }
           

這裡根據success的值又會調用一個函數,其實好像調用的函數是一樣的:

dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
           

都是server_input_keep_alive函數,這個函數的意思就很簡單了:

static voidserver_input_keep_alive(int type, u_int32_t seq, void *ctxt){    debug("Got %d/%u for keepalive", type, seq);    /*     * reset timeout, since we got a sane answer from the client.     * even if this was generated by something other than     * the bogus CHANNEL_REQUEST we send for keepalives.     */    packet_set_alive_timeouts(0);}
           

packet_set_alive_timeouts(0)就是把active_state->keep_alive_timeouts的值設為0,也就是重置了這個計數。

是以饒了一圈,這些代碼的意思大概應該是這樣,如果用戶端在規定時間内沒有響應,就先判斷未響應次數是否超過設定的值,如果超過就結束。

如果沒超過,就把這個次數加1,然後發送一個請求,看看用戶端還在不在,如果用戶端網絡正常(應該會自動回複),就會得到用戶端的回複,于是就重置這個未響應計數。

四、兩個方式的不同

TMOUT方式可以針對所有使用者通過本地tty或遠端ssh登入時起作用,而修改sshd_config隻針對使用ssh登入的使用者。

另外一點就是TMOUT判斷你有沒有在操作,好像是看你有沒有輸入什麼字元然後敲回車執行,你輸入正确的指令敲回車執行指令,就算。輸入無意義的字元敲回車沒有找到可執行的指令,那也算。光輸入字元不敲回車就不算,而判斷你處于空閑狀态,逾時就會登出。

而ssh是基于網絡來判斷,隻要用戶端對伺服器有發送資訊,那就算有在操作。

這也是兩者的一些細微的不同之處。

*本文原創作者:起于凡而非于凡,本文屬于FreeBuf原創獎勵計劃,未經許可禁止轉載

centos iptables_等保測評:Centos逾時退出詳解

精彩推薦

centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解
centos iptables_等保測評:Centos逾時退出詳解