{"id":"IL-0452","org":"Hyperconnect","date":"2024-06-24","docs":["https://my.f5.com/manage/s/article/K60036398","https://my.f5.com/manage/s/article/K15097"],"title":{"en":"Azar users on one carrier's 3G IP pool in one country increasingly hit read timed out errors on a STOMP connection","ko":"한 나라의 한 통신사 3G IP 대역을 쓰는 Azar 사용자가 STOMP 로 통신하는 컴포넌트에 연결하지 못하고 read timed out 을 반복해서 겪었다"},"domain":["networking"],"impact":{"scope":"Azar users on carrier Z's 3G IP pool in country XY could not connect to component A over STOMP and got read timed out errors, many of them repeatedly","users":"As of 2024-03-26: 1,322 users with one error, 1,471 with 2 to 10, 798 with 10 to 100 and 147 with more than 100","region":"One country, called XY in the write-up"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"In the retrospective the SRE team named as a problem that it started looking at the issue only as CS reports piled up, at least three months after it first appeared. A global service can lose connectivity for some users because a local network changes unexpectedly, and such problems can badly hurt the experience in a major country.","ko":"SRE 팀은 회고에서, 첫 문제가 생기고 최소 3개월이 지나 CS 가 쌓인 뒤에야 문제를 보기 시작했다는 점을 짚었다. 글로벌 서비스에서는 예상하지 못한 지역 네트워크의 변화 때문에 일부 사용자가 회사 인프라에 제대로 연결하지 못할 수 있다. 팀은 이 문제를 다음 순서로 풀었다. 데이터 분석으로 볼 곳을 정하고, 문제 구간을 좁혀 모바일 프록시로 재현하고, 원인을 찾아 테스트한 뒤 핫픽스를 배포했다."},"related":[],"sources":[{"url":"https://hyperconnect.github.io/2024/06/24/global-network-troubleshooting.html","kind":"blog","archived":"https://web.archive.org/web/20260510101113/https://hyperconnect.github.io/2024/06/24/global-network-troubleshooting.html"}],"summary":{"en":"Hyperconnect's Azar app connects to component A over the STOMP protocol. The team's existing tool for monitoring regional network connectivity ran from data centres and supported only a limited set of protocols, so it could not test STOMP from mobile networks, and the team had no way to track problems in part of one local network. The SRE team therefore used Oxylabs, a SaaS that provides mobile SOCKS5 proxies by country, and before each connect request fetched https://ifconfig.co/json to learn which carrier the proxy device was on, since the carrier could not be chosen.\n\nThe first clue was that a plain curl request through an HTTP proxy got a quick answer even for the affected users. Comparing the reproducing script with earlier code that had failed to reproduce the problem showed the difference: whether the TLS Client Hello carried SNI. The library used for STOMP did not include SNI in TLS connections by default. This had not been a problem until recently; the team estimates that carrier Z gradually rolled out QoS settings based on SNI, and found that example configurations for software such as F5's Local Traffic Manager make it easy to drop packets without SNI or send them to a separate pool.\n\nThe Android and iOS teams shipped hotfixes that add SNI. Before release the team compared versions with and without SNI through SOCKS proxies, using the tun2socks app on Android and ShadowRocket on iOS. The iOS hotfix also fixed the bug in timeout error reporting. As adoption of the new versions rose, the errors fell gradually and the related CS reports stopped.","ko":"Hyperconnect 는 Azar 를 전 세계에 서비스한다. 2024년 1월 XY 국가의 극히 일부 사용자가 컴포넌트 A 와 관련된 오류를 겪는다는 CS 가 들어왔다. 그러나 컴포넌트 A 에는 변경이 없었고 서비스 지표도 크게 나빠지지 않아, 팀은 단서를 찾지 못한 채 넘어갔다. 그 뒤 관련 CS 가 12월 말부터 3월 셋째 주까지 선형적으로 늘었다는 리포트가 올라왔다. 기존 모니터링으로는 지역 네트워크의 일부에서만 생기는 문제를 추적할 수 없었다. 원인을 못 찾으면 그 나라로 출장까지 고려해야 할 상황이었다.\n\nSRE 팀은 CS 시트와 Databricks 의 클라이언트 에러 로그를 분석해, 신고가 모두 통신사 Z 에서 왔고 Android 의 read timed out 이 점점 늘고 있다는 것을 알아냈다. 이 오류는 컴포넌트 A 와의 STOMP 커넥션이 시간 안에 맺어지지 않을 때 난다. 이 오류를 10번 넘게 겪은 사용자는 900명이 넘었다. Global Accelerator 로 지역 ISP 에서 AWS 까지의 경로를 바꿔도 변화가 없어 문제를 지역 네트워크 안으로 좁혔다. 기존 연결성 모니터링 솔루션으로는 모바일 환경에서 STOMP 를 시험할 수 없었다. 그래서 팀은 나라별 모바일 기기를 SOCKS5 프록시로 쓰게 해 주는 Oxylabs 를 썼다. 재현해 보니 통신사 Z 의 3G IP pool 에 붙은 기기에서만 응답이 오기까지 40초에서 2분이 걸려 timeout 이 났다.\n\n재현이 되는 SRE 팀의 코드와 재현이 안 되던 다른 코드를 비교하니, TLS Client Hello 에 SNI 를 넣는지만 달랐다. STOMP 통신에 쓰던 라이브러리는 기본으로 SNI 를 넣지 않았다. 팀은 통신사 Z 가 SNI 유무에 따라 QoS pool 을 조절하는 설정을 조금씩 rolling update 로 적용하면서 오류가 늘었다고 추정했다. Android 팀과 iOS 팀이 SNI 를 넣는 핫픽스를 만들었다. 두 팀은 tun2socks 와 ShadowRocket 으로 SOCKS 프록시를 거쳐 동작 차이를 확인한 뒤 핫픽스를 배포했다. iOS 에서 오류 패턴이 보이지 않았던 것은 timeout 오류를 리포팅하는 로직의 버그 때문이었고, 이 버그도 같은 핫픽스에서 고쳤다. 새 버전을 쓰는 사용자가 늘면서 오류가 점점 줄었고 관련 CS 는 더 들어오지 않았다."},"trigger":{"en":"The team cautiously estimates that carrier Z was gradually rolling out a setting that adjusts the QoS pool depending on whether a TLS connection includes SNI, so the hourly error count kept growing.","ko":"STOMP 통신에 쓰던 라이브러리는 기본 설정에서 TLS Client Hello 에 SNI 를 넣지 않았다. SRE 팀은 통신사 Z 가 SNI 유무에 따라 QoS pool 을 조절하는 설정을 조금씩 rolling update 로 적용하면서 오류가 늘었다고 추정했다."},"severity":"unknown","symptoms":["intermittent-timeouts"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":{"en":"Customer-support reports from users in country XY reached the internal CS channel in January 2024; the problem was taken up only after a report showed those reports rising steadily into March.","ko":"XY 국가의 일부 사용자가 보낸 CS 가 내부 CS 논의 채널로 들어오면서 알게 됐다. 처음에는 원인을 못 찾고 넘어갔고, 관련 CS 가 계속 늘어난다는 리포트가 올라온 뒤에야 본격적으로 조사했다."},"components":["isp-network"],"root_cause":"dns-network","remediation":[{"text":{"en":"Shipped Android and iOS hotfixes that include SNI in the TLS connection to component A","ko":"Android 팀과 iOS 팀이 STOMP 통신의 TLS 연결에 SNI 를 넣는 핫픽스를 만들었다. SNI 를 넣은 버전과 넣지 않은 버전을 Android 는 tun2socks, iOS 는 ShadowRocket 으로 SOCKS 프록시에 연결해 두 버전의 동작 차이를 확인한 뒤 배포했다."}},{"text":{"en":"Fixed the iOS bug in reporting timeout errors in the same hotfix","ko":"iOS 에서 timeout 오류를 리포팅하는 로직의 버그를 같은 핫픽스에서 고쳤다."}}],"action_items":[{"text":{"en":"Use mobile proxy services such as Oxylabs to test connectivity to core components from global networks automatically and collect metrics","ko":"Oxylabs 같은 모바일 프록시 솔루션으로 여러 나라의 네트워크 환경에서 핵심 컴포넌트의 연결성을 자동으로 시험하고 메트릭을 모은다. 장애가 나면 이 메트릭으로 더 빨리 대처한다."}}],"contributing":["default-config-unchanged","monitoring-blind-spot"],"recurrence_of":null,"symptoms_text":{"en":"In January 2024 a few customer-support reports came in through Hyperconnect's internal CS channel: some Azar users in one country, called XY in the write-up, reported a problem, and the errors pointed to an internal component called A. Component A had not changed around that time, service metrics did not visibly worsen and the reports were very few, so the teams found no lead and went back to other work.\n\nLater a report showed that the related CS cases kept coming and rose linearly, from x at the end of December to the third week of March. In the client error logs, which Hyperconnect analyses in near real time with Databricks and an internal platform, about 20 of several hundred error types appeared more than 1,000 times a day. Only one of them, on Android, grew steadily: read timed out, which the Android app reports when its connection to component A is not made in time. Filtering for one carrier, called Z, showed the same rising trend at almost the same absolute numbers. As of 2024-03-26, 1,322 users had hit the error once, 1,471 two to ten times, 798 ten to 100 times and 147 more than 100 times, which pointed to repeated failures making Azar unusable for them. iOS showed no such pattern because of a bug in the logic that reports timeout errors.\n\nComponent A served traffic from every country, so the team ruled out the application, and the long duration ruled out an AWS outage. Routing country XY's traffic to component A through Global Accelerator, so that the local network connected straight onto AWS's network, did not change the error trend, which narrowed the problem to the local network. The affected users timed out only on STOMP connections to component A, not on all traffic.\n\nTo reproduce it, the SRE team connected Azar's golang STOMP test script through Oxylabs mobile SOCKS5 proxies in country XY. Only devices on a specific IP range of carrier Z, a 3G IP pool, got answers very late, after 40 seconds to 2 minutes, far beyond the connection timeout, and a user who failed once kept failing on retries.","ko":"2024년 1월 내부 CS 논의 채널에 XY 국가의 극히 일부 사용자가 Azar 에서 컴포넌트 A 와 관련된 오류를 겪는다는 제보가 들어왔다. 클라이언트에서는 몇 가지 에러 메시지가 꽤 많이 나고 있었다. 그러나 그 무렵 컴포넌트 A 에는 바뀐 것이 없었고 서비스 지표도 눈에 띄게 나빠지지 않았다.\n\n관련 CS 는 12월 말부터 3월 셋째 주까지 선형적으로 늘었다. CS 를 모은 시트에서 통신사 정보가 있는 신고는 모두 통신사 Z 를 가리켰고, 안드로이드와 iOS 의 차이는 크게 보이지 않았다.\n\nDatabricks 로 클라이언트 에러 로그를 보니 하루 1,000회가 넘는 에러 타입 약 20개 중 점점 늘어나는 것은 Android 의 read timed out 하나였다. Android 팀은 이 오류가 컴포넌트 A 와의 커넥션이 시간 안에 맺어지지 않을 때 나는 것이라고 확인했다. 통신사 Z 로 걸러 보니 같은 증가 추이가 그대로 나타났다.\n\n같은 사용자가 같은 오류를 반복해서 겪었다. 2024년 3월 26일 기준으로 오류를 1번 겪은 사용자는 1,322명, 2~10번은 1,471명, 10~100번은 798명, 100번 넘게 겪은 사용자는 147명이었다. timeout 은 모든 통신에서 나지 않고 컴포넌트 A 와의 STOMP 통신에서만 났다.\n\nSRE 팀은 컴포넌트 A 가 모든 나라의 트래픽을 받고 있으므로 애플리케이션 문제는 아니라고 보았다. 현상이 오래 이어졌으므로 AWS 장애도 아니라고 판단했다. Global Accelerator 로 지역 네트워크에서 바로 AWS 회선으로 들어오게 경로를 바꿨지만 에러 추이는 변하지 않았다. 그래서 문제를 지역 네트워크 안으로 좁혔다.\n\n팀은 Oxylabs 의 모바일 SOCKS5 프록시와 golang 으로 짠 STOMP 테스트 스크립트로 현상을 재현했다. 통신사 Z 의 3G IP pool 에 해당하는 특정 IP 대역에 붙은 기기에서만 응답이 오기까지 40초에서 2분이 걸렸다. 클라이언트의 timeout 은 이보다 훨씬 짧아서 요청은 모두 timeout 으로 끝났다. 한 번 연결이 안 된 사용자는 다시 요청해도 계속 느렸다. 같은 사용자라도 curl 로 HTTP 프록시를 거쳐 요청하면 응답이 금방 돌아왔다."},"updated_at":"2026-11-14T12:34:10.097291Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0452","org_slug":"hyperconnect"}