Skip to content

Implement TLS VerifyPeerCertificate callback to skip hostname verfication#238

Open
zzzming wants to merge 4 commits into
apache:masterfrom
zzzming:ValidateHostName
Open

Implement TLS VerifyPeerCertificate callback to skip hostname verfication#238
zzzming wants to merge 4 commits into
apache:masterfrom
zzzming:ValidateHostName

Conversation

@zzzming
Copy link
Copy Markdown
Contributor

@zzzming zzzming commented May 3, 2020

Contribution Checklist

This PR addresses a problem how to disable TLS ValidateHostname. The current implementation with empty tlsConfig.ServerName would not work, because the connected server host will be inferred in absence of tlsConfig.ServerName by Go Tls library. One of the use cases is when DNS name in the server certificate returned does not match the broker host name that the client connects to. The client can be deployed within the same Pulsar kubernetes cluster if the client connects to the internal proxy or broker host directly instead of the public fqdn. This problem may also rise for self-signed cert.

This specific problem and solution are described by this issue report, golang/go#21971

This PR implements a TLS VerifyPeerCertificate callback to skip host name validation if any client chooses to disable TLSValidateHostname in ClientOption.

I understand TLSValidateHostname is false by default because Go initializes bool as false. There is an existing issue #171 that is tracking the problem. I think it will open up a discussion how to support backward compatibility that might require consensus from the community. Therefore, altering the current default is beyond the scope of this PR.

Does this pull request potentially affect one of the following parts:

If yes was chosen, please highlight the changes

  • Dependencies (does it add or upgrade a dependency): (no)
  • The public API: (yes) Yes the current implementation of skip hostname check is broken, this is a fix.
  • The schema: (no)
  • The default values of configurations: (no)
  • The wire protocol: (no)

Documentation

  • Does this pull request introduce a new feature? (no)
  • If yes, how is the feature documented? (not applicable)

@wolfstudy wolfstudy requested review from merlimat and wolfstudy May 15, 2020 05:33
@wolfstudy wolfstudy added this to the 0.1.1 milestone May 15, 2020
Copy link
Copy Markdown
Member

@wolfstudy wolfstudy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, LGTM +1

Comment thread pulsar/internal/connection.go Outdated
@@ -713,6 +713,41 @@ func (c *connection) getTLSConfig() (*tls.Config, error) {

if c.tlsOptions.ValidateHostname {
tlsConfig.ServerName = c.physicalAddr.Hostname()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support SNI, shouldn't the tlsConfig.ServerName be set in all cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EronWright you are right that ServerName should be set as suggested by https://github.com/golang/go/blob/62a3f2e27c7732656bb3ae8f14047b74a9956e77/src/crypto/tls/common.go#L542
I think the problem is the default value of TLSValidateHostname is false. It should have been called DisabledTLSValidateHostname. Do you have any suggestion how to handle backward compatibility of TLSValidateHostname?
I made an update to add ServerName but only skip verification if InsecureSkipVerify is true.

@wolfstudy wolfstudy modified the milestones: 0.1.1, 0.2.0 Jun 9, 2020
@wolfstudy
Copy link
Copy Markdown
Member

Move this change to 0.2.0

@wolfstudy
Copy link
Copy Markdown
Member

ping @EronWright PTAL

client.Close()
}

func TestTLSInsecureConnectionWithCerts(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn't seem to do anything substantive. I'd expect it to exercise the resultant tls.Config in some way, maybe by making an actual TLS connection.

tlsConfig.ServerName = c.physicalAddr.Hostname()
tlsConfig.ServerName = c.physicalAddr.Hostname()

if tlsConfig.InsecureSkipVerify {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't c.tlsOptions.ValidateHostname used anywhere? I was thinking:

tlsConfig := &tls.Config{
    // disable built-in verification if hostname verification is to be skipped
		InsecureSkipVerify: c.tlsOptions.AllowInsecureConnection || !c.tlsOptions.ValidateHostname
	}

if !c.tlsOptions.AllowInsecureConnection && tlsConfig.InsecureSkipVerify {
  // implement a limited verification routine that checks the certificate but skips hostname verification 
  tlsConfig.VerifyPeerCertificate = func() {...}
}

Comment on lines +733 to +735
if tlsConfig.RootCAs == nil {
return nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would this deal with the common scenario where the client is using the system's bundle? I am unsure of whether RootCAs is nil in that scenario.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ran into this. As-is verification will return success when no roots are loaded.

@wolfstudy
Copy link
Copy Markdown
Member

ping @zzzming Can you check @EronWright comments? thanks.

@wolfstudy wolfstudy modified the milestones: 0.2.0, 0.3.0 Aug 24, 2020
@wolfstudy wolfstudy modified the milestones: 0.3.0, 0.4.0 Nov 11, 2020
@wolfstudy wolfstudy modified the milestones: 0.4.0, 0.5.0 Feb 9, 2021
@merlimat merlimat modified the milestones: 0.5.0, 0.6.0 May 11, 2021
@wolfstudy wolfstudy modified the milestones: 0.6.0, 0.7.0 Jul 21, 2021
@wolfstudy wolfstudy modified the milestones: 0.7.0, v0.8.0 Nov 1, 2021
@wolfstudy wolfstudy modified the milestones: v0.8.0, 0.9.0 Feb 16, 2022
@freeznet freeznet modified the milestones: v0.9.0, v0.10.0 Jul 4, 2022
@nodece
Copy link
Copy Markdown
Member

nodece commented Dec 2, 2022

This PR is cool, any updates?

@RobertIndie RobertIndie modified the milestones: v0.10.0, v0.11.0 Mar 27, 2023
@RobertIndie RobertIndie modified the milestones: v0.11.0, v0.12.0 Jul 4, 2023
@RobertIndie RobertIndie modified the milestones: v0.12.0, v0.13.0 Jan 10, 2024
@RobertIndie RobertIndie modified the milestones: v0.13.0, v0.14.0 Jul 15, 2024
@RobertIndie RobertIndie modified the milestones: v0.14.0, v0.15.0 Oct 8, 2024
@RobertIndie RobertIndie modified the milestones: v0.15.0, v0.16.0 May 15, 2025
@RobertIndie RobertIndie modified the milestones: v0.16.0, v0.17.0 Jul 29, 2025
@RobertIndie RobertIndie modified the milestones: v0.17.0, v0.18.0 Oct 23, 2025
@RobertIndie RobertIndie modified the milestones: v0.18.0, v0.19.0 Dec 1, 2025
@RobertIndie RobertIndie modified the milestones: v0.19.0, 0.20.0 Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants