Невелика проксі-обгортка може працювати для HTTPS, а потім зависати, коли її повторно використовують для протоколу, сервер якого говорить першим. Підозрілий рядок — зазвичай той, що чекає, поки буфер приймання закінчиться послідовністю \r\n\r\n.

TCP дає клієнтові потік. Один виклик приймання може повернути половину рядка стану HTTP, повну відповідь CONNECT або цю відповідь одразу з даними тунелю. Немає жодної гарантії, що читання зупиниться на кінці заголовків.

Знайдіть межу всередині буфера

Для обміну HTTP/1.1 CONNECT накопичуйте байти, доки термінатор заголовків не з’явиться будь-де в буфері. Розділіть за першим його входженням. Розберіть рядок стану та заголовки з першої частини; усе після межі зберігайте окремо. Застосовуйте обмеження розміру заголовків і тайм-аут під час очікування, а порожнє читання сокета вважайте закритим з’єднанням, а не новим запрошенням до циклу.

Остання успішна відповідь 2xx переводить з’єднання в режим тунелю одразу після цих заголовків. Наступні за нею байти — уже байти тунелю. Не відкидайте їх, не чекайте на тіло відповіді CONNECT і не трактуйте поле Content-Length як дозвіл спожити частину нового протоколу. Інформаційні відповіді, якщо вони є, треба обробити до цієї фінальної відповіді.

Обгортка має передавати свої залишки

Повернення лише базового сокета втрачає байти, які парсер рукостискання вже витяг із нього. Наступному читачеві потрібен буферизований потік, який спершу віддає збережений хвіст, а потім відновлює читання із сокета. Для протоколу, де сервер говорить першим, втрата цього початкового привітання може залишити обидві сторони в нескінченному очікуванні.

І навпаки, байти невдалої відповіді CONNECT не є привітанням тунелю. 407 і далі належить до обміну з проксі й потребує обробки автентифікації; інший неуспішний статус потребує належного шляху помилки.

Це особливо важливо під час адаптації клієнта FTP або SSH через HTTP-проксі. Проксі також має дозволяти запитаний порт призначення, а FTP може потребувати додаткових з’єднань даних. Правильний розбір заголовків вирішує передачу потоку; він не може надати дозвіл CONNECT чи забезпечити другий канал FTP.

Схожі статті