-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support TLS by socket/server plugin helper #1423
Changes from all commits
c1945a4
e4cd065
6ca47e8
5a72ae1
00c2a2a
30d00f7
43d1656
876b295
3198105
8cda021
055ec94
6aabce5
0648788
1090a18
bfdec29
e68fb95
9a011dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<source> | ||
@type forward | ||
port 24224 | ||
<transport tls> | ||
insecure true | ||
</transport> | ||
</source> | ||
|
||
<match test> | ||
@type stdout | ||
# <buffer> | ||
# flush_interval 10s | ||
# </buffer> | ||
</match> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<source> | ||
@type dummy | ||
tag test | ||
</source> | ||
|
||
<match test> | ||
@type forward | ||
transport tls | ||
tls_insecure_mode true | ||
<server> | ||
# first server | ||
host 127.0.0.1 | ||
port 24224 | ||
</server> | ||
<buffer> | ||
flush_interval 0 | ||
</buffer> | ||
</match> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,12 +33,17 @@ class ConnectionClosedError < Error; end | |
|
||
LISTEN_PORT = 24224 | ||
|
||
desc 'The transport protocol.' | ||
config_param :transport, :enum, list: [:tcp, :tls], default: :tcp | ||
# TODO: TLS session cache/tickets | ||
# TODO: Connection keepalive | ||
|
||
desc 'The timeout time when sending event logs.' | ||
config_param :send_timeout, :time, default: 60 | ||
# TODO: add linger_timeout, recv_timeout | ||
|
||
desc 'The transport protocol to use for heartbeats.(udp,tcp,none)' | ||
config_param :heartbeat_type, :enum, list: [:tcp, :udp, :none], default: :tcp | ||
desc 'The protocol to use for heartbeats (default is the same with "transport").' | ||
config_param :heartbeat_type, :enum, list: [:transport, :tcp, :udp, :none], default: :transport | ||
desc 'The interval of the heartbeat packer.' | ||
config_param :heartbeat_interval, :time, default: 1 | ||
desc 'The wait time before accepting a server fault recovery.' | ||
|
@@ -75,6 +80,19 @@ class ConnectionClosedError < Error; end | |
desc 'Compress buffered data.' | ||
config_param :compress, :enum, list: [:text, :gzip], default: :text | ||
|
||
desc 'The default version of TLS transport.' | ||
config_param :tls_version, :enum, list: Fluent::PluginHelper::Socket::TLS_SUPPORTED_VERSIONS, default: Fluent::PluginHelper::Socket::TLS_DEFAULT_VERSION | ||
desc 'The cipher configuration of TLS transport.' | ||
config_param :tls_ciphers, :string, default: Fluent::PluginHelper::Socket::CIPHERS_DEFAULT | ||
desc 'Skip all verification of certificates or not.' | ||
config_param :tls_insecure_mode, :bool, default: false | ||
desc 'Allow self signed certificates or not.' | ||
config_param :tls_allow_self_signed_cert, :bool, default: false | ||
desc 'Verify hostname of servers and certificates or not in TLS transport.' | ||
config_param :tls_verify_hostname, :bool, default: true | ||
desc 'The additional CA certificate path for TLS.' | ||
config_param :tls_cert_path, :array, value_type: :string, default: nil | ||
|
||
config_section :security, required: false, multi: false do | ||
desc 'The hostname' | ||
config_param :self_hostname, :string | ||
|
@@ -85,7 +103,7 @@ class ConnectionClosedError < Error; end | |
config_section :server, param_name: :servers do | ||
desc "The IP address or host name of the server." | ||
config_param :host, :string | ||
desc "The name of the server. Used in log messages." | ||
desc "The name of the server. Used for logging and certificate verification in TLS transport (when host is address)." | ||
config_param :name, :string, default: nil | ||
desc "The port number of the host." | ||
config_param :port, :integer, default: LISTEN_PORT | ||
|
@@ -136,9 +154,29 @@ def configure(conf) | |
@read_interval = @read_interval_msec / 1000.0 | ||
@recover_sample_size = @recover_wait / @heartbeat_interval | ||
|
||
if @heartbeat_type == :tcp | ||
log.warn "'heartbeat_type tcp' is deprecated. use 'transport' instead." | ||
@heartbeat_type = :transport | ||
end | ||
|
||
if @dns_round_robin | ||
if @heartbeat_type == :udp | ||
raise Fluent::ConfigError, "forward output heartbeat type must be 'tcp' or 'none' to use dns_round_robin option" | ||
raise Fluent::ConfigError, "forward output heartbeat type must be 'transport' or 'none' to use dns_round_robin option" | ||
end | ||
end | ||
|
||
if @transport == :tls | ||
if @tls_cert_path && !@tls_cert_path.empty? | ||
@tls_cert_path.each do |path| | ||
raise Fluent::ConfigError, "specified cert path does not exist:#{path}" unless File.exist?(path) | ||
raise Fluent::ConfigError, "specified cert path is not readable:#{path}" unless File.readable?(path) | ||
end | ||
end | ||
|
||
if @tls_insecure_mode | ||
log.warn "TLS transport is configured in insecure way" | ||
@tls_verify_hostname = false | ||
@tls_allow_self_signed_cert = true | ||
end | ||
end | ||
|
||
|
@@ -275,14 +313,34 @@ def select_a_healthy_node | |
raise NoNodesAvailable, "no nodes are available" | ||
end | ||
|
||
def create_transfer_socket(host, port, &block) | ||
socket_create_tcp( | ||
host, port, | ||
linger_timeout: @send_timeout, | ||
send_timeout: @send_timeout, | ||
recv_timeout: @ack_response_timeout, | ||
&block | ||
) | ||
def create_transfer_socket(host, port, hostname, &block) | ||
case @transport | ||
when :tls | ||
socket_create_tls( | ||
host, port, | ||
version: @tls_version, | ||
ciphers: @tls_ciphers, | ||
insecure: @tls_insecure_mode, | ||
verify_fqdn: @tls_verify_hostname, | ||
fqdn: hostname, | ||
allow_self_signed_cert: @tls_allow_self_signed_cert, | ||
cert_paths: @tls_cert_path, | ||
linger_timeout: @send_timeout, | ||
send_timeout: @send_timeout, | ||
recv_timeout: @ack_response_timeout, | ||
&block | ||
) | ||
when :tcp | ||
socket_create_tcp( | ||
host, port, | ||
linger_timeout: @send_timeout, | ||
send_timeout: @send_timeout, | ||
recv_timeout: @ack_response_timeout, | ||
&block | ||
) | ||
else | ||
raise "BUG: unknown transport protocol #{@transport}" | ||
end | ||
end | ||
|
||
# MessagePack FixArray length is 3 | ||
|
@@ -458,6 +516,14 @@ def initialize(sender, server, failure:) | |
@available = true | ||
@state = nil | ||
|
||
# @hostname is used for certificate verification & TLS SNI | ||
host_is_hostname = !(IPAddr.new(@host) rescue false) | ||
@hostname = case | ||
when host_is_hostname then @host | ||
when @name then @name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I changed the meaning of |
||
else nil | ||
end | ||
|
||
@usock = nil | ||
|
||
@username = server.username | ||
|
@@ -557,7 +623,7 @@ def send_data_actual(sock, tag, chunk) | |
end | ||
|
||
def send_data(tag, chunk) | ||
sock = @sender.create_transfer_socket(resolved_host, port) | ||
sock = @sender.create_transfer_socket(resolved_host, port, @hostname) | ||
begin | ||
send_data_actual(sock, tag, chunk) | ||
rescue | ||
|
@@ -589,8 +655,8 @@ def send_heartbeat | |
end | ||
|
||
case @sender.heartbeat_type | ||
when :tcp | ||
@sender.create_transfer_socket(dest_addr, port) do |sock| | ||
when :transport | ||
@sender.create_transfer_socket(dest_addr, port, @hostname) do |sock| | ||
## don't send any data to not cause a compatibility problem | ||
# sock.write FORWARD_TCP_HEARTBEAT_DATA | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
tls_
prefix instead of<tls>
is for avoiding confustion with<transport tls>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you mentioned, these parameters are named in different way from servers'
<transport>
section.I think that almost users just specify one or (at most) two parameters in these
tls_
prefixed parameters (tls_cert_path
, and sometimestls_allow_self_signed_cert
). Many users don't change the default TLS version nor TLS ciphers.In such cases,
tls_cert_path ...
is much more simple than<tls> tls_cert_path ... </tls>
.