Module: Falcon::Environment::Proxy

Includes:
Server
Defined in:
lib/falcon/environment/proxy.rb

Overview

Provides an environment for hosting a TLS-capable reverse proxy using SNI.

Instance Method Summary collapse

Methods included from Server

#authority, #cache, #client_endpoint, #container_options, #preload, #service_class, #timeout, #verbose

Instance Method Details

#endpointObject

The endpoint the server will bind to.



96
97
98
99
100
# File 'lib/falcon/environment/proxy.rb', line 96

def endpoint
	super.with(
		ssl_context: self.ssl_context,
	)
end

#environmentsObject

The services we will proxy to.



29
30
31
# File 'lib/falcon/environment/proxy.rb', line 29

def environments
	[]
end

#host_context(socket, hostname) ⇒ Object

Look up the host context for the given hostname, and update the socket hostname if necessary.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/falcon/environment/proxy.rb', line 59

def host_context(socket, hostname)
	hosts = self.hosts
	
	if host = hosts[hostname]
		Console.logger.debug(self) {"Resolving #{hostname} -> #{host}"}
		
		socket.hostname = hostname
		
		return host.ssl_context
	else
		Console.logger.warn(self, hosts: hosts.keys) {"Unable to resolve #{hostname}!"}
		
		return nil
	end
end

#hostsObject

The hosts we will proxy to. This is a hash of SNI authority -> evaluator.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/falcon/environment/proxy.rb', line 35

def hosts
	hosts = {}
	
	environments.each do |environment|
		evaluator = environment.evaluator
		
		# next unless environment.implements?(Falcon::Environment::Application)
		if evaluator.key?(:authority) and evaluator.key?(:ssl_context) and evaluator.key?(:endpoint)
			Console.info(self) {"Proxying #{self.url} to #{evaluator.authority} using #{evaluator.endpoint}"}
			hosts[evaluator.authority] = evaluator
			
			if RUBY_VERSION < '3.1'
				# Ensure the SSL context is set up before forking - it's buggy on Ruby < 3.1:
				evaluator.ssl_context
			end
		end
	end
	
	return hosts
end

#middlewareObject



102
103
104
# File 'lib/falcon/environment/proxy.rb', line 102

def middleware
	return Middleware::Proxy.new(Middleware::BadRequest, self.hosts)
end

#ssl_contextObject

Generate an SSL context which delegates to #host_context to multiplex based on hostname.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/falcon/environment/proxy.rb', line 76

def ssl_context
	@server_context ||= OpenSSL::SSL::SSLContext.new.tap do |context|
		context.servername_cb = Proc.new do |socket, hostname|
			self.host_context(socket, hostname)
		end
		
		context.session_id_context = @session_id
		
		context.ssl_version = :TLSv1_2_server
		
		context.set_params(
			ciphers: ::Falcon::TLS::SERVER_CIPHERS,
			verify_mode: ::OpenSSL::SSL::VERIFY_NONE,
		)
		
		context.setup
	end
end

#tls_session_idObject

The default SSL session identifier.



23
24
25
# File 'lib/falcon/environment/proxy.rb', line 23

def tls_session_id
	"falcon"
end

#urlObject

The host that this proxy will receive connections for.



18
19
20
# File 'lib/falcon/environment/proxy.rb', line 18

def url
	"https://[::]:443"
end