Commit 2ffe8f5
committed
Fix TLS hostname validation bug and add configurable validation (akkadotnet#7897)
* Fix TLS hostname validation bug and add configurable validation (akkadotnet#7893)
## Summary
This commit addresses GitHub issue akkadotnet#7893 by fixing a critical TLS hostname validation bug and introducing a configurable, type-safe validation system.
## Changes
### Bug Fix
- **Fixed DotNettyTransport.cs:355** - TLS client was incorrectly validating against the client's own certificate DNS name instead of the remote server address
- Changed from `certificate.GetNameInfo(X509NameType.DnsName, false)` to `remoteAddress.Host`
### New Configuration
- Added `validate-certificate-hostname` config option to Remote.conf
- Default: `false` (disabled for backward compatibility and mutual TLS flexibility)
- When enabled: Traditional TLS hostname validation (CN/SAN must match target hostname)
- When disabled: Only validates certificate chain, ignores hostname mismatches
- Useful for: Mutual TLS with per-node certificates, IP-based connections, dynamic service discovery
### Type-Safe Validation System
- Introduced enums to prevent primitive confusion in security-critical code:
- `ChainValidationMode` enum (ValidateChain, IgnoreChainErrors)
- `HostnameValidationMode` enum (ValidateHostname, IgnoreHostnameMismatch)
- Created `TlsValidationCallbacks` static factory class with:
- Main `Create()` method accepting enum parameters and logging adapter
- Convenience methods: `ValidateFull()`, `ValidateChainOnly()`, `ValidateHostnameOnly()`, `AcceptAll()`
- Detailed error logging with filtered SslPolicyErrors
- Makes validation flags independent and composable
- Replaces ~35 lines of inline callback code with 3 lines of self-documenting factory calls
### Updated SslSettings
- Added `ValidateCertificateHostname` property
- Updated all constructors to accept the new property
- Updated `Create()` method to read from HOCON config
### Test Coverage
- Extended `DotNettyMutualTlsSpec` with 4 new test cases:
- `Hostname_validation_disabled_should_allow_different_certificates()` - Different certs work with validation disabled
- `Hostname_validation_enabled_should_reject_different_certificates()` - Different certs fail with validation enabled
- `Same_certificate_should_connect_in_mutual_tls()` - Typical mutual TLS scenario
- `Hostname_validation_default_should_be_disabled()` - Verifies backward compatibility
## Technical Details
Chain validation and hostname validation are now fully independent:
- `suppressValidation=true` disables chain/CA validation (for self-signed certs)
- `validateCertificateHostname=true/false` controls hostname matching (for per-node certs, IPs)
This allows testing hostname validation with self-signed certificates by using `suppressValidation=true, validateCertificateHostname=true`.
Fixes akkadotnet#7893
* Extend DotNettySslSetup to expose all SSL/TLS configuration options
## Summary
Extended `DotNettySslSetup` programmatic API to expose the full SSL/TLS configuration, including the newly added hostname validation setting and the existing RequireMutualAuthentication setting that was previously only available via HOCON.
## Changes
### DotNettySslSetup API
- Added `RequireMutualAuthentication` property (was missing from programmatic API)
- Added `ValidateCertificateHostname` property (new setting from akkadotnet#7893)
- Added comprehensive XML documentation for all properties and constructors
- Added backward-compatible constructors:
- 2-parameter: Defaults to RequireMutualAuthentication=true, ValidateCertificateHostname=false
- 3-parameter: Defaults to ValidateCertificateHostname=false
- 4-parameter: Full control over all settings
- Updated `Settings` property to pass all 4 parameters to `SslSettings` constructor
### Integration Tests
- Added 3 integration tests in `DotNettySslSetupSpec`:
- Verify 2-parameter setup configures effective DotNettyTransportSettings with expected defaults
- Verify 3-parameter setup configures effective settings with specified RequireMutualAuth
- Verify 4-parameter setup configures effective settings with all specified values
- Tests verify the actual consumption path: ActorSystem → DotNettyTransportSettings.Create() → setup.Value.Settings
- Tests validate that setup values correctly override HOCON defaults
## Backward Compatibility
All existing code using the 2-parameter constructor continues to work with the same defaults:
- RequireMutualAuthentication: true (matches previous HOCON-only behavior)
- ValidateCertificateHostname: false (matches new HOCON default)
The setup is properly consumed in `DotNettyTransportSettings.Create(ActorSystem)` which retrieves the setup via `system.Settings.Setup.Get<DotNettySslSetup>()` and calls `setup.Value.Settings` to get the fully configured `SslSettings` object.
* Update security documentation for hostname validation feature
## Changes
- Explained the new independent validation system (chain vs hostname)
- Added details about default certificate stores used (Windows, Linux, macOS)
- Documented the `validate-certificate-hostname` setting with use cases
- Added validation mode combination table
- Included configuration examples for both P2P and client-server scenarios
- Added comprehensive troubleshooting for hostname validation errors
- Documented enhanced TLS error messages from v1.5.52
- Reduced emoji usage for more professional tone
- Added links to Microsoft documentation and RFC specifications
## Key Documentation Updates
### New Sections
- Certificate Validation: Independent Control
- Hostname Validation setting explanation
- Validation Mode Combinations table
- Configuration with Hostname Validation Enabled
- Enhanced error message examples
### Troubleshooting Additions
- RemoteCertificateNameMismatch errors (hostname validation failures)
- UntrustedRoot errors (chain validation failures)
- Understanding TLS Error Messages section with real examples
- Multiple fix options for each error scenario
### Technical Details
- Explained which OS certificate stores are used by default
- Referenced RFC 5280 and RFC 6125 for validation standards
- Clarified that suppress-validation only controls chain validation
- Clarified that hostname validation is separate and optional
* Fix markdown linting and spellcheck issues in security docs
- Add blank lines around all fenced code blocks
- Add language specifiers to code blocks (text, hocon, bash, powershell)
- Change dash lists to asterisk lists for consistency
- Add 'hostnames' to spellcheck dictionary
- Emphasize that hostname validation defaults to false (disabled)
* Improve documentation heading structure and title case
- Remove technical setting names from headings
- Use descriptive section titles instead
- Change subheadings to 'Enabled/Disabled' pattern
- Move technical details into content body
- Fix title case linting issues
This makes the documentation more scannable and separates conceptual
sections from implementation details.
* added api approvals1 parent 109aa3d commit 2ffe8f5
File tree
10 files changed
+793
-70
lines changed- docs
- articles/remoting
- src/core
- Akka.API.Tests/verify
- Akka.Remote.Tests/Transport
- Akka.Remote
- Configuration
- Transport/DotNetty
10 files changed
+793
-70
lines changedLarge diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
| |||
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
863 | 863 | | |
864 | 864 | | |
865 | 865 | | |
| 866 | + | |
| 867 | + | |
866 | 868 | | |
| 869 | + | |
867 | 870 | | |
| 871 | + | |
868 | 872 | | |
869 | 873 | | |
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
863 | 863 | | |
864 | 864 | | |
865 | 865 | | |
| 866 | + | |
| 867 | + | |
866 | 868 | | |
| 869 | + | |
867 | 870 | | |
| 871 | + | |
868 | 872 | | |
869 | 873 | | |
Lines changed: 165 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
52 | 56 | | |
53 | 57 | | |
54 | 58 | | |
55 | 59 | | |
| 60 | + | |
56 | 61 | | |
57 | 62 | | |
58 | 63 | | |
| |||
275 | 280 | | |
276 | 281 | | |
277 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
278 | 442 | | |
279 | 443 | | |
280 | 444 | | |
| |||
Lines changed: 90 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
108 | 198 | | |
109 | 199 | | |
110 | 200 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
565 | 565 | | |
566 | 566 | | |
567 | 567 | | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
568 | 580 | | |
569 | 581 | | |
570 | 582 | | |
| |||
0 commit comments