hyperium / tonic

A native gRPC client & server implementation with async/await support.
https://docs.rs/tonic
MIT License
9.81k stars 998 forks source link

IPv6 endpoint passed through the URL will crash #1696

Open gezihuzi opened 5 months ago

gezihuzi commented 5 months ago

Bug Report

Version

ambiguous_methods v0.1.0 (/Users/chen/source/tonic/tests/ambiguous_methods)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build)
codegen v0.1.0 (/Users/chen/source/tonic/codegen)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build)
compression v0.1.0 (/Users/chen/source/tonic/tests/compression)
├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
default_stubs v0.1.0 (/Users/chen/source/tonic/tests/default_stubs)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
disable-comments v0.1.0 (/Users/chen/source/tonic/tests/disable_comments)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
examples v0.1.0 (/Users/chen/source/tonic/examples)
├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
├── tonic-health v0.11.0 (/Users/chen/source/tonic/tonic-health)
│   └── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
├── tonic-reflection v0.11.0 (/Users/chen/source/tonic/tonic-reflection)
│   └── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
│   └── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
├── tonic-types v0.11.0 (/Users/chen/source/tonic/tonic-types)
│   └── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
├── tonic-web v0.11.0 (/Users/chen/source/tonic/tonic-web)
│   ├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
included_service v0.1.0 (/Users/chen/source/tonic/tests/included_service)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
integration v0.1.0 (/Users/chen/source/tonic/tonic-web/tests/integration)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
└── tonic-web v0.11.0 (/Users/chen/source/tonic/tonic-web) (*)
integration-tests v0.1.0 (/Users/chen/source/tonic/tests/integration_tests)
├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
interop v0.1.0 (/Users/chen/source/tonic/interop)
├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
my_application v0.1.0 (/Users/chen/source/tonic/tests/extern_path/my_application)
├── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── uuid1 v0.1.0 (/Users/chen/source/tonic/tests/extern_path/uuid)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
root-crate-path v0.1.0 (/Users/chen/source/tonic/tests/root-crate-path)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
same_name v0.1.0 (/Users/chen/source/tonic/tests/same_name)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
service_named_result v0.1.0 (/Users/chen/source/tonic/tests/service_named_result)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
service_named_service v0.1.0 (/Users/chen/source/tonic/tests/service_named_service)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
stream_conflict v0.1.0 (/Users/chen/source/tonic/tests/stream_conflict)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
tonic-health v0.11.0 (/Users/chen/source/tonic/tonic-health) (*)
tonic-reflection v0.11.0 (/Users/chen/source/tonic/tonic-reflection) (*)
tonic-types v0.11.0 (/Users/chen/source/tonic/tonic-types) (*)
tonic-web v0.11.0 (/Users/chen/source/tonic/tonic-web) (*)
use_arc_self v0.1.0 (/Users/chen/source/tonic/tests/use_arc_self)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
uuid1 v0.1.0 (/Users/chen/source/tonic/tests/extern_path/uuid) (*)
wellknown v0.1.0 (/Users/chen/source/tonic/tests/wellknown)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)
wellknown-compiled v0.1.0 (/Users/chen/source/tonic/tests/wellknown-compiled)
└── tonic v0.11.0 (/Users/chen/source/tonic/tonic) (*)
└── tonic-build v0.11.0 (/Users/chen/source/tonic/tonic-build) (*)

Platform

Darwin Chen.local 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:10:42 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T6000 arm64

Description

When I make a request to an local IPv6 endpoint using this code, the program crashes.

let dst = "https://[fd1b:aeaa:6cd1:1747:1403:a845:82e5:fcf6]:15220";
let verifier = Arc::new(NoVerifier());
let tls_config = ClientTlsConfig::new().verifier(verifier);
let endpoint = Channel::from_shared(dst)
        .map_err(|e| Error::InvalidUri(e.to_string()))?
        .tls_config(tls_config)?;
let channel = endpoint.connect().await?;

I found that the IpAddr cannot be parsed correctly because the parameter passed in when resolving the service address was not processed at all.

In the source code of tonic:

https://github.com/hyperium/tonic/blob/068421a0bdd966eada1cc2aab70fa0845a4bb87a/tonic/src/transport/channel/tls.rs#L72-L83

The code here directly obtains the corresponding domain information through uri.host(). Then it is passed into TlsConnector::new.

After passing in the parameters, construct TlsConnector:

https://github.com/hyperium/tonic/blob/068421a0bdd966eada1cc2aab70fa0845a4bb87a/tonic/src/transport/service/tls.rs#L37-L71

In line 68 of the code, construct ServerName by passing parameters through ServerName::try_from. It crashes here.

The reason is that the domain information obtained by uri.host() includes [ and ], which prevents the IPv6 address from being resolved correctly here.