mirror of
https://github.com/dalbodeule/hop-gate.git
synced 2025-12-09 13:25:44 +09:00
[feat](protocol): enforce 4KiB hard limit on Protobuf body and stream payloads
- Added safeguards to restrict HTTP body and stream payload sizes to 4KiB (`StreamChunkSize`) in the Protobuf codec. - Updated client logic to apply consistent limits for streaming and non-streaming scenarios. - Improved error handling with clear messages for oversized payloads.
This commit is contained in:
@@ -57,6 +57,24 @@ func (protobufCodec) Encode(w io.Writer, env *Envelope) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Body/stream payload 하드 리밋: 4KiB (StreamChunkSize).
|
||||
// HTTP 단일 Envelope 및 스트림 기반 프레임 모두에서 payload 가 이 값을 넘지 않도록 강제합니다.
|
||||
// Enforce a 4KiB hard limit (StreamChunkSize) for HTTP bodies and stream payloads.
|
||||
switch env.Type {
|
||||
case MessageTypeHTTP:
|
||||
if env.HTTPRequest != nil && len(env.HTTPRequest.Body) > int(StreamChunkSize) {
|
||||
return fmt.Errorf("protobuf codec: http request body too large: %d bytes (max %d)", len(env.HTTPRequest.Body), StreamChunkSize)
|
||||
}
|
||||
if env.HTTPResponse != nil && len(env.HTTPResponse.Body) > int(StreamChunkSize) {
|
||||
return fmt.Errorf("protobuf codec: http response body too large: %d bytes (max %d)", len(env.HTTPResponse.Body), StreamChunkSize)
|
||||
}
|
||||
case MessageTypeStreamData:
|
||||
if env.StreamData != nil && len(env.StreamData.Data) > int(StreamChunkSize) {
|
||||
return fmt.Errorf("protobuf codec: stream data payload too large: %d bytes (max %d)", len(env.StreamData.Data), StreamChunkSize)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(pbEnv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("protobuf marshal envelope: %w", err)
|
||||
|
||||
@@ -192,18 +192,25 @@ func (p *ClientProxy) forwardToLocal(ctx context.Context, preq *protocol.Request
|
||||
}
|
||||
|
||||
// DTLS over UDP has an upper bound on packet size (~64KiB). 전체 HTTP 바디를
|
||||
// 하나의 JSON Envelope 로 감싸 전송하는 현재 설계에서는 바디가 너무 크면
|
||||
// 하나의 Envelope 로 감싸 전송하는 현재 설계에서는, 바디가 너무 크면
|
||||
// OS 레벨에서 "message too long" (EMSGSIZE) 가 발생할 수 있습니다. (ko)
|
||||
//
|
||||
// 이를 피하기 위해, 터널링 가능한 바디 크기에 상한을 두고, 이를 초과하는
|
||||
// 응답은 502 Bad Gateway + HopGate 전용 에러 메시지로 대체합니다. (ko)
|
||||
// 이를 피하기 위해, 터널링 가능한 **단일 HTTP 바디** 크기에 상한을 두고,
|
||||
// 이를 초과하는 응답은 502 Bad Gateway + HopGate 전용 에러 메시지로 대체합니다. (ko)
|
||||
//
|
||||
// DTLS over UDP has an upper bound on datagram size (~64KiB). With the current
|
||||
// design (wrapping the entire HTTP body into a single JSON envelope), very
|
||||
// large bodies can trigger "message too long" (EMSGSIZE) at the OS level.
|
||||
// To avoid this, we cap the tunneled body size and replace oversized responses
|
||||
// with a 502 Bad Gateway + HopGate-specific error body. (en)
|
||||
const maxTunnelBodyBytes = 48 * 1024 // 48KiB, conservative under UDP limits
|
||||
// single-envelope design, very large bodies can still trigger "message too long"
|
||||
// (EMSGSIZE) at the OS level. To avoid this, we cap the tunneled HTTP body size
|
||||
// and replace oversized responses with a 502 Bad Gateway + HopGate-specific
|
||||
// error body. (en)
|
||||
//
|
||||
// Protobuf 기반 터널링에서는 향후 StreamData(4KiB) 단위로 나누어 전송할 예정이지만,
|
||||
// 그 전 단계에서도 body 자체를 4KiB( StreamChunkSize )로 하드 리밋하여
|
||||
// Proto message body 필드가 지나치게 커지지 않도록 합니다. (ko)
|
||||
//
|
||||
// Even before full stream tunneling is implemented, we hard-limit the protobuf
|
||||
// body field to 4KiB (StreamChunkSize) so that individual messages remain small. (en)
|
||||
const maxTunnelBodyBytes = protocol.StreamChunkSize
|
||||
|
||||
limited := &io.LimitedReader{
|
||||
R: res.Body,
|
||||
|
||||
Reference in New Issue
Block a user