日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

現在大部分軟硬件系統都是基于網絡的,有走局域網(私網)的,有走外網(公網)的,會不可避免地出現很多與網絡相關的問題,特別是將產品部署到安全級別較高的客戶環境中,會出現各式各樣的復雜網絡問題。今天我們就來分享一下實際項目中遇到的多個網絡問題,以供參考!

1、windows防火墻攔截了客戶端發來的TCP連接請求,導致客戶端與服務器建鏈失敗

這是一個Windows系統自帶的防火墻攔截程序網絡數據的例子。客戶端和服務器程序運行在兩臺Windows電腦上,客戶端需要連接到遠端的服務器上獲取數據,但客戶端始終連接不上遠端的服務器。用Wireshark抓包看,客戶端給服務器發送TCP三次握手的SYN包,服務器始終沒有回應,導致TCP連接始終無法建立。

我們先是ping了服務器所在機器的IP地址,是能ping通的。又在服務器所在電腦上使?.NETstat -a命令查看到服務器的9001端口是出于Listening監聽狀態的。

如下所示:


 

這就奇怪了,服務器的ip能ping的通的,服務器的端口也處于正常的監聽狀態,為啥始終沒法和服務器建鏈呢?

后來想到我們在Widnows系統上第一次運行程序時,一般都會彈出類似下面的截圖:

一般情況下我們使用默認的選擇,沒有全部勾選,直接就點擊下面的“允許訪問”的按鈕了。窗口中提示Windows防火墻已經阻止了部分功能,應該是將公網網絡和專網網絡都勾選上的,估計是Windows防火墻將發給該服務器程序的部分數據包攔截了,于是將服務器程序所在系統的Windows防火墻關閉,然后客戶端可以正常連接了。

其實可以在服務器側抓包,客戶端發來的用于三次握手的SYN包,服務器所在機器的網卡應該收到了,只是向應用層傳遞數據時數據被防火墻攔截了。

最終的解決辦法是允許該服務器程序能通過防火墻進行通信,在控制面板中點擊系統和安全->Widnows Defender防火墻->允許應用或功能通過Windows防火墻,在打開的界面中找到服務器程序:

將專用網絡和公用都勾上,點擊確定就好了。即允許服務器程序通過防火墻進行通信,防火墻就不會攔截發給服務器的數據包了。

2、在linux服務器側抓包選錯網卡,導致服務器側的抓包信息與客戶端的對不上

客戶端和服務器通信的過程中出現了問題,導致業務出現了異常,于是要在客戶端和服務端兩側抓包,對照兩邊的網絡數據包,看看到底是哪一側出問題了。

客戶端運行在Windows系統中,直接啟動WireShark就可以直擊抓包了。服務器運行在遠端的Linux系統上,需要使用SSH工具遠程登錄到Linux系統中,然后使用tcpdump命令進行抓包,然后再將抓包文件下載到Windows系統中,然后使用WireShark打開查看。

打開服務器的抓包文件后,發現有問題,和客戶端抓的數據包對不上,服務器側的抓包文件中顯示的服務器IP地址,和終端側抓包文件中顯示的服務器IP地址是不一致的。服務器側抓到的包中顯示的是服務器IP是內網的IP,而終端側抓包顯示連接的服務器IP是外網的IP,所以兩邊對不上的,后來想起來可能輸入tcpdump命令時選錯了網卡導致的。

后經平臺側的運維同事確認,Linux服務器上確實有兩張物理網卡,在Linux命令行中使用ifconfig命令就可以查看到服務器上的網卡信息,一個是配置了內網的eth0網卡,一個是配置了外網IP的eth1網卡:

所以要修改之前輸入的tcpdump命令,命令中指定抓eth1網卡的數據包:

 

tcpdump -i eth1 -s 0 -w dvsserver.pcap

 

或者抓所有網卡的數據包:

 

tcpdump -i any -s 0 -w dvsserver.pcap

3、升級服務器的端口改變了,導致軟件無法進行在線升級

 

某日測試同事在客戶端軟件上發起在線版本監測,結果始終連不上服務器。使用wireshark抓包看到,軟件在發送TCP三次握手的SYN包后,遠端服務器直接回了個RST包,強行將客戶端的連接請求給終止了。

首先,服務器回包了,那服務器肯定是能ping通的,于是使用telnet命令檢測升級服務器的63000服務端口是否正常,結果該端口是連不上的。一般情況下直接回復RST可能是端口不存在引起的,經后來和升級服務器開發確認,升級服務器的端口已經變更了,不再是之前的60000端口號了。

其實這個問題中,還有兩點是有問題的:

 

(1)客戶端軟件側處理的有問題,不應該將升級服務器的端口在代碼中固定為某個數字,應該使用登錄時平臺返回的升級服務器端口。 (2)平臺變更端口后應該發郵件通知客戶端側,平臺側應該對老的客戶端提供兼容支持,老的版本已經發布已經交付給客戶使用,平臺要對老版本做兼容,應該做個端口重定向,老版本使用60000端口發起連接時應該重定向到最新的端口上。

 

4、Linux服務器系統中開啟了reuse和recycle選項,導致客戶端會時不時連不上服務器

有用戶反饋軟件客戶端會時不時出現無法登錄服務器的問題。使用Wireshark抓包看,客戶端在發出三次握手的SYN包,始終收不到服務器的ACK包,甚至觸發了客戶端的丟包重傳,即多次發送SYN包,服務器都沒有回應,導致客戶端和服務器建TCP連接失敗。

后來在平臺側也進行了抓包,發現服務器確實收到了客戶端發來的SYN包,但就是沒有回ACK應答包。經排查得知,服務器的Linux系統的TCP/IP協議棧開啟了reuse和recycle選項,這和協議棧的timestamp時間戳策略會沖突,如果短時間內多次收到SYN包,平臺側TCP/IP協議棧會直接將請求拒絕掉,不給SYN包發送端任何回應。

服務器側這兩個選項一般都不能開啟,特別是tcp_tw_recycle選項開啟后,可能會導致部分連接請求不響應,導致連接失敗。在服務器側,可以通過命令直接將這兩個選項關閉掉:

echo 0 > /proc/sys/net/IPv4/tcp_tw_reuseecho 0 > /proc/sys/net/ipv4/tcp_tw_recycle

關于這兩個選項的說明如下:

 

(1)tcp_tw_reuse:主要用于端口復用,用在客戶端側,將其設置為1表示允許將TIME-WAIT sockets重新用于新的TCP連接,默認為0,表示關閉。(2)tcp_tw_recycle:將其設置為1表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉。

5、Windows系統中使用雙網卡時,可能需要添加策略路由

 

在一臺測試用的Windows PC機上,配置了兩張網卡,一張是連接外網的網卡,用于上外網;一張是連接內網的網卡,用于連局域網

如下:

而Windows操作系統只允許設置一個默認網關,所以只能有一個網卡配置默認網關,一般是連接外網的網卡配置默認網關,因為外網的IP地址是不固定的。內網的網卡則不配置網關,對于內網的IP地址是相對固定的,比如以192.168開頭的、以172.16開頭的、以10.開頭的。當要訪問這些地址時,可以通過添加策略路由的方式指定訪問這些開頭的IP地址從指定的局域網的網關出去。

只要是有網卡配置了默認網關,都會在路由表中添加一條走默認網關的默認路由,如下所示:

通過命令去添加策略路由時,也會向系統中添加對應的路由條目,添加策略路由的命令如下:

route add 172.16.0.0 mask 255.255.0.0 172.16.125.88(內網的網關)

這條添加路由命令的含義是:所有訪問以172.16開頭的IP地址,都從網關172.16.125.88出去。

當我們發起對一個IP地址的訪問時(也可能通過域名去訪問,會先將域名解析為IP地址,然后用IP地址去訪問),系統在查找路由時,會優先匹配系統的非默認路由,即會匹配添加的策略路由,當匹配不上時才會去使用默認路由。

所以,訪問外網的地址時會走連接外網的網卡出去,訪問以192.168開頭的、以172.16開頭的等內網地址時,會走策略路由中指定的連接內網的網關出去。

6、連接線路中的網絡設備將客戶端與其之間的連接單方面關閉掉,導致后續登錄服務器時出現異常

在公司局域網的測試環境中,客戶端自動重連服務器出現問題。根據打印日志發現,客戶端和服務器之間的TCP長連接因為網絡問題出現斷鏈,客戶端在收到斷鏈通知后,會去自動重連服務器,但始終都連接不上。

根據打印日志看到,服務器返回的錯誤碼是用戶已登錄。這個就奇怪了,明明是客戶端收到與服務器的連接斷開的通知后去重連的,為啥服務器側還反饋我們的賬號還處于登錄狀態呢?既然連接斷了,服務器應該也能感知到的,賬戶不太可能還出于連接狀態的!

于是使用SSH遠程登錄到服務器上,使用netstat查看服務器當前的TCP連接列表,在列表中看到了客戶端的IP,客戶端居然和服務器還處于連接狀態。

于是找公司大牛幫忙排查分析一下,他查下來懷疑可能是客戶端與服務器之間的路由器單方面將路由器與客戶端之間的鏈路給斷開了,但路由器與服務器之間的鏈路還保持著,還沒斷開。該路由器是好多年前購買的老式華為路由器,可能是路由器有問題,估計是因為客戶端與服務器長時間沒有數據交互,路由器認為客戶端與其的鏈路失去活性了,強行將其與客戶端之間的鏈路釋放了。

客戶端與服務器之間使用websocket網絡庫(libwebsockets開源庫)進行通信的,libwebsockets庫支持開啟心跳機制、設置心跳參數的。為了解決連接鏈路上長時間不跑數據導致鏈路被釋放問題,在初始化libwebsockets庫時,設置一下心跳參數就可以了。

libwebsockets庫中設置心跳參數的結構體如下所示:

* struct lws_context_creation_info - parameters to create context with* This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS* is not given, then for backwards compatibility one vhost is created at* context-creation time using the info from this struct.* If LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, then no vhosts are created* at the same time as the context, they are expected to be created afterwards.* @port: VHOST: Port to listen on... you can use CONTEXT_PORT_NO_LISTEN to* suppress listening on any port, that's what you want if you are* not running a websocket server at all but just using it as a* client* @iface: VHOST: to bind the listen socket to all interfaces, or the* interface name, eg, "eth2"* If options specifies LWS_SERVER_OPTION_UNIX_SOCK, this member is* the pathname of a UNIX domain socket. you can use the UNIX domain* sockets in abstract namespace, by prepending an @ symbole to the* socket name.* @protocols: VHOST: Array of structures listing supported protocols and a protocol-* specific callback for each one. The list is ended with an* entry that has a callback pointer.* It's not const because we write the owning_server member* @extensions: VHOST: or array of lws_extension structs listing the* extensions this context supports. If you configured with* --without-extensions, you should give here.* @token_limits: CONTEXT: or struct lws_token_limits pointer which is initialized* with a token length limit for each possible WSI_TOKEN_**** @ssl_cert_filepath: VHOST: If libwebsockets was compiled to use ssl, and you want* to listen using SSL, set to the filepath to fetch the* server cert from, otherwise for unencrypted* @ssl_private_key_filepath: VHOST: filepath to private key if wanting SSL mode;* if this is set to but sll_cert_filepath is set, the* OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called* to allow setting of the private key directly via openSSL* library calls* @ssl_ca_filepath: VHOST: CA certificate filepath or* @ssl_cipher_list: VHOST: List of valid ciphers to use (eg,* "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!a"* or you can leave it as to get "DEFAULT"* @http_proxy_address: VHOST: If non-, attempts to proxy via the given address.* If proxy auth is required, use format* "username:password@server:port"* @http_proxy_port: VHOST: If http_proxy_address was non-, uses this port at* the address* @gid: CONTEXT: group id to change to after setting listen socket, or -1.* @uid: CONTEXT: user id to change to after setting listen socket, or -1.* @options: VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields* @user: CONTEXT: optional user pointer that can be recovered via the context* pointer using lws_context_user* @ka_time: CONTEXT: 0 for no keepalive, otherwise Apply this keepalive timeout to* all libwebsocket sockets, client or server* @ka_probes: CONTEXT: if ka_time was nonzero, after the timeout expires how many* times to try to get a response from the peer before giving up* and killing the connection* @ka_interval: CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes* attempt* @provided_client_ssl_ctx: CONTEXT: If non-, swap out libwebsockets ssl* implementation for the one provided by provided_ssl_ctx.* Libwebsockets no longer is responsible for freeing the context* if this option is selected.* @max_http_header_data: CONTEXT: The max amount of header payload that can be handled* in an http request (unrecognized header payload is dropped)* @max_http_header_pool: CONTEXT: The max number of connections with http headers that* can be processed simultaneously (the corresponding memory is* allocated for the lifetime of the context). If the pool is* busy new incoming connections must wait for accept until one* becomes free.* @count_threads: CONTEXT: how many contexts to create in an array, 0 = 1* @fd_limit_per_thread: CONTEXT: nonzero means restrict each service thread to this* many fds, 0 means the default which is divide the process fd* limit by the number of threads.* @timeout_secs: VHOST: various processes involving network roundtrips in the* library are protected from hanging forever by timeouts. If* nonzero, this member lets you set the timeout used in seconds.* Otherwise a default timeout is used.* @ecdh_curve: VHOST: if , defaults to initializing server with "prime256v1"* @vhost_name: VHOST: name of vhost, must match external DNS name used to* access the site, like "warmcat.com" as it's used to match* Host: header and / or SNI name for SSL.* @plugin_dirs: CONTEXT: , or -terminated array of directories to* scan for lws protocol plugins at context creation time* @pvo: VHOST: pointer to optional linked list of per-vhost* options made accessible to protocols* @keepalive_timeout: VHOST: (default = 0 = 60s) seconds to allow remote* client to hold on to an idle HTTP/1.1 connection* @log_filepath: VHOST: filepath to append logs to... this is opened before* any dropping of initial privileges* @mounts: VHOST: optional linked list of mounts for this vhost* @server_string: CONTEXT: string used in HTTP headers to identify server* software, if , "libwebsockets".struct lws_context_creation_info {int port; /* VH */const char *iface; /* VH */const struct lws_protocols *protocols; /* VH */const struct lws_extension *extensions; /* VH */const struct lws_token_limits *token_limits; /* context */const char *ssl_private_key_password; /* VH */const char *ssl_cert_filepath; /* VH */const char *ssl_private_key_filepath; /* VH */const char *ssl_ca_filepath; /* VH */const char *ssl_cipher_list; /* VH */const char *http_proxy_address; /* VH */unsigned int http_proxy_port; /* VH */int gid; /* context */int uid; /* context */unsigned int options; /* VH + context */void *user; /* context */int ka_time; /* context */int ka_probes; /* context */int ka_interval; /* context */#ifdef LWS_OPENSSL_SUPPORTSSL_CTX *provided_client_ssl_ctx; /* context */#else /* maintain structure layout either way */void *provided_client_ssl_ctx;#endifshort max_http_header_data; /* context */short max_http_header_pool; /* context */unsigned int count_threads; /* context */unsigned int fd_limit_per_thread; /* context */unsigned int timeout_secs; /* VH */const char *ecdh_curve; /* VH */const char *vhost_name; /* VH */const char * const *plugin_dirs; /* context */const struct lws_protocol_vhost_options *pvo; /* VH */int keepalive_timeout; /* VH */const char *log_filepath; /* VH */const struct lws_http_mount *mounts; /* VH */const char *server_string; /* context *//* Add new things just above here ---^* This is part of the ABI, don't needlessly break compatibility* The below is to ensure later library versions with new* members added above will see 0 (default) even if the app* was not built against the newer headers.void *_unused[8];

上述結構體中的ka_time、ka_interval和ka_probes三個字段,是心跳參數,這三個參數的含義是:

 

ka_time:兩個心跳包之間的時間間隔; ka_interval:給對端發送心跳包之后,收不到對端ACK確認超時時間; ka_probes:心跳包探測次數。

 

我們在調用lws_create_context接口初始化libwebsockets庫時,可以指定這三個參數

static lws_context* CreateContext{lws_set_log_level( 0xFF, );lws_context* plcContext = ;lws_context_creation_info tCreateinfo;memset(&tCreateinfo, 0, sizeof tCreateinfo);tCreateinfo.port = CONTEXT_PORT_NO_LISTEN;tCreateinfo.protocols = protocols;tCreateinfo.ka_time = 10; // 心跳包間的時間間隔tCreateinfo.ka_interval = 10; // 發出心跳包后沒有收到ACK確認包時重發心跳包的超時時間tCreateinfo.ka_probes = 3; // 心跳探測次數,對于windows操作系統,此設置是無效的,Windows系統時固定為10次,不可修改tCreateinfo.options = LWS_SERVER_OPTION_DISABLE_IPV6;plcContext = lws_create_context(&tCreateinfo);return plcContext;}

跟進libwebsockets庫的開源代碼中,函數lws_create_context的內部,最終調用的是lws_plat_set_socket_options接口,該接口內部最終是給對應的socket套接字設置心跳參數的,如下:

LWS_VISIBLE intlws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd){int optval = 1;int optlen = sizeof(optval);u_long optl = 1;DWORD dwBytesRet;struct tcp_keepalive alive;int protonbr;#ifndef _WIN32_WCEstruct protoent *tcp_proto;#endifif (vhost->ka_time) {/* enable keepalive on this socket */// 先調用setsockopt打開發送心跳包(設置)選項optval = 1;if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,(const char *)&optval, optlen) < 0)return 1;alive.onoff = TRUE;alive.keepalivetime = vhost->ka_time*1000;alive.keepaliveinterval = vhost->ka_interval*1000;if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),, 0, &dwBytesRet, , ))return 1;}/* Disable Nagle */optval = 1;#ifndef _WIN32_WCEtcp_proto = getprotobyname("TCP");if (!tcp_proto) {lwsl_err("getprotobyname failed with error %dn", LWS_ERRNO);return 1;}protonbr = tcp_proto->p_proto;#elseprotonbr = 6;#endifsetsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen);/* We are nonblocking... */ioctlsocket(fd, FIONBIO, &optl);return 0;}

所以libwebsockets庫的心跳設置,使用的還是TCPIP協議棧的心跳,不是應用層自己實現的心跳機制。

關于TCPIP協議棧的三個心跳參數的詳細說明如下:

 

(1)keepalivetime:心跳正常時,本端發送一個心跳包給對端,收到對端心跳包的回應,間隔keepalivetime時間后,發下一包心跳包,windows默認的心跳包發送間隔是2小時。 (2)keepaliveinterval:心跳異常時,本端發送心跳包后沒收到對端的回應,間隔keepaliveinterval時間后,發送下一個心跳包(繼續探測)。如果多次沒有收到對端的回應,當探測次數達到上限(keep-alive probes)時,則協議棧認為連接出問題。 (3)keep-alive probes:windows系統中 ,心跳包探測次數keep-alive probes是不可改變的,協議棧固定為10次。

7、在復雜網絡環境中主從服務器切換時遇到的多個網絡異常問題

 

主服務器和從服務器共用一個IP,當主服務器出問題時,切換到從服務器上,然后服務器以組播的方式將搶IP的數據包發出去,這個數據包始終沒有發出來,導致搶IP操作失敗。通過排查得知,組播數據包會被客戶網絡環境中的一臺華為路由器攔截,可能是這臺華為路由器有問題,但客戶要求我們從我們服務器這一側去修改,后來將多播改成單播才解決問題。

客戶的網絡設備上配置了很多安全規則,其中一個規則是將IP-mac地址綁定,如果設備的IP和MAC地址對不上,設備發出來的數據包就會被網絡設備認為是不安全的數據,會直接被攔截。在從服務器拿到主服務器的IP之后,IP對應的MAC地址就變了,正好就觸發了這個IP-MAC綁定規則,導致數據包被攔截。后來的解決辦法是將主從服務器公用的IP作為特例進行放行,即對這個IP不進行攔截。

8、Linux系統的TCP/IP協議棧重定向選項被關閉,無法響應網關發來的ICMP重定向消息,導致收發數據時出現嚴重的丟包問題

給客戶部署的系統中,有臺設備放置于某個網絡節點下,給該設備配置了該節點下的默認網關,結果聯調下來發現,所有的其他節點下的其他設備都沒問題,就這臺設備有問題,這臺設備發出來的數據有嚴重的丟包問題。

現場人員和客戶一起做了對比測試,把客戶之前購買的別的廠商的設備放置在該網絡節點下,別的廠商的設備都沒有丟包問題,就我們公司的設備有問題。期間,我們給客戶調撥了一個我們幾年前研發的一款老式設備,放置在該節點下也沒問題,就當前使用的新式設備有問題。

這個問題折騰的比較久,始終沒有查出來問題,后來找公司的頂級專家來排查,才查出來問題。這臺設備發出去的數據,默認情況下都要通過其配置的默認網關發出去,抓包發現,默認網關會給設備發了ICMP重定向消息,該消息中攜帶一個IP地址,該消息是用來告訴設備,要發送數據都從這個IP發出去。

一般情況下,協議棧在收到這個ICMP重定向消息后,會向系統路由表中添加一條路由,這樣要發送的數據會使用這條路由中的IP發送出去。通過大量的抓包分析之后,找到了問題的癥結,是因為設備內置的Linux系統的TCP/IP協議棧的重定向選項都被關閉導致的,在linux命令行使用命令sysctrl -a | grep redirects可以查看到:

我們硬件設備中的使用的Linux系統是經過裁剪后部署進去的,之前在系統裁剪時,出于安全考慮,將系統的TCP/IP網絡協議棧中所有重定向選項都關閉了,所以此案例中默認網關發過來的ICMP重定向消息被丟棄了,導致發出的數據還是發到默認網關上,但從默認網關出去的數據會有明顯的丟包問題(客戶網絡環境故意這么處理的,不讓數據從默認網關出去),所以出現了最開始出現的問題。

此問題的臨時解決辦法是手動將這些重定向選項打開,后續進行Linux系統裁剪時要將這些重定向選項打開。

原作者:dvlinker

源鏈接:https://blog.csdn.net/chenlycly/article/details/124643918

編輯:IT運維技術圈

分享到:
標簽:網絡
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定