itsi-server 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +950 -239
- data/README.md +2 -0
- data/exe/itsi +5 -5
- data/ext/itsi_acme/Cargo.toml +86 -0
- data/ext/itsi_acme/examples/high_level.rs +63 -0
- data/ext/itsi_acme/examples/high_level_warp.rs +52 -0
- data/ext/itsi_acme/examples/low_level.rs +87 -0
- data/ext/itsi_acme/examples/low_level_axum.rs +66 -0
- data/ext/itsi_acme/src/acceptor.rs +81 -0
- data/ext/itsi_acme/src/acme.rs +354 -0
- data/ext/itsi_acme/src/axum.rs +86 -0
- data/ext/itsi_acme/src/cache.rs +39 -0
- data/ext/itsi_acme/src/caches/boxed.rs +80 -0
- data/ext/itsi_acme/src/caches/composite.rs +69 -0
- data/ext/itsi_acme/src/caches/dir.rs +106 -0
- data/ext/itsi_acme/src/caches/mod.rs +11 -0
- data/ext/itsi_acme/src/caches/no.rs +78 -0
- data/ext/itsi_acme/src/caches/test.rs +136 -0
- data/ext/itsi_acme/src/config.rs +172 -0
- data/ext/itsi_acme/src/https_helper.rs +69 -0
- data/ext/itsi_acme/src/incoming.rs +142 -0
- data/ext/itsi_acme/src/jose.rs +161 -0
- data/ext/itsi_acme/src/lib.rs +142 -0
- data/ext/itsi_acme/src/resolver.rs +59 -0
- data/ext/itsi_acme/src/state.rs +424 -0
- data/ext/itsi_server/Cargo.toml +3 -3
- data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +2 -2
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +150 -19
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +1 -0
- data/ext/itsi_server/src/server/binds/listener.rs +34 -29
- data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +2 -2
- data/ext/itsi_server/src/server/binds/tls.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middleware.rs +33 -28
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +56 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +179 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +25 -2
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +3 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +2 -1
- data/ext/itsi_server/src/server/middleware_stack/mod.rs +32 -34
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +10 -4
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +30 -7
- data/ext/itsi_server/src/server/thread_worker.rs +2 -2
- data/ext/itsi_server/src/services/static_file_server.rs +30 -28
- data/ext/itsi_tracing/src/lib.rs +39 -8
- data/lib/itsi/server/config/config_helpers.rb +93 -0
- data/lib/itsi/server/config/dsl.rb +81 -33
- data/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
- data/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
- data/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
- data/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
- data/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
- data/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
- data/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
- data/lib/itsi/server/config/known_paths/cms/README.md +5 -0
- data/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
- data/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
- data/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
- data/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
- data/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
- data/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
- data/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
- data/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
- data/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
- data/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
- data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
- data/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
- data/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
- data/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
- data/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
- data/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
- data/lib/itsi/server/config/known_paths/tftp.txt +79 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
- data/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
- data/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
- data/lib/itsi/server/config/known_paths.rb +17 -0
- data/lib/itsi/server/config/middleware/_index.md +54 -0
- data/lib/itsi/server/config/middleware/log_requests.md +63 -0
- data/lib/itsi/server/config/middleware/log_requests.rb +33 -0
- data/lib/itsi/server/config/middleware.rb +9 -0
- data/lib/itsi/server/config/option.rb +9 -0
- data/lib/itsi/server/config/options/_index.md +36 -0
- data/lib/itsi/server/config/options/fiber_scheduler.md +35 -0
- data/lib/itsi/server/config/options/fiber_scheduler.rb +18 -0
- data/lib/itsi/server/config/options/threads.md +39 -0
- data/lib/itsi/server/config/options/threads.rb +17 -0
- data/lib/itsi/server/config/options/workers.md +43 -0
- data/lib/itsi/server/config/options/workers.rb +17 -0
- data/lib/itsi/server/config/typed_struct.rb +203 -0
- data/lib/itsi/server/config.rb +124 -30
- data/lib/itsi/server/signal_trap.rb +5 -1
- data/lib/itsi/server/typed_handlers/source_parser.rb +1 -1
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +27 -6
- data/lib/ruby_lsp/itsi/addon.rb +64 -48
- metadata +141 -5
- data/CHANGELOG.md +0 -10
- data/CODE_OF_CONDUCT.md +0 -139
- data/LICENSE.txt +0 -21
- data/_index.md +0 -6
data/README.md
CHANGED
data/exe/itsi
CHANGED
@@ -7,9 +7,10 @@ require "optparse"
|
|
7
7
|
|
8
8
|
COMMANDS = {
|
9
9
|
"init" => "Initialize a new Itsi.rb server configuration file",
|
10
|
+
"test" => "Test config file validity",
|
10
11
|
"status" => "Show the status of the server",
|
11
|
-
"start" => "Start the
|
12
|
-
"serve" => "Start the
|
12
|
+
"start" => "Start the Itsi server",
|
13
|
+
"serve" => "Start the Itsi server",
|
13
14
|
"stop" => "Stop the server",
|
14
15
|
"reload" => "Reload the server",
|
15
16
|
"restart" => "Restart the server",
|
@@ -37,7 +38,7 @@ parser = OptionParser.new do |opts|
|
|
37
38
|
end
|
38
39
|
|
39
40
|
opts.on("-d", "--daemonize", "Run the process as a daemon") do
|
40
|
-
|
41
|
+
options[:daemonize] = true
|
41
42
|
end
|
42
43
|
|
43
44
|
opts.on("-t", "--threads THREADS", Integer, "Number of threads (default: 1)") do |t|
|
@@ -57,7 +58,7 @@ parser = OptionParser.new do |opts|
|
|
57
58
|
options[:worker_memory_limit] = ml
|
58
59
|
end
|
59
60
|
|
60
|
-
opts.on("-f", "--fiber_scheduler [CLASS_NAME]",
|
61
|
+
opts.on("-f", "--fiber_scheduler [CLASS_NAME]", String,
|
61
62
|
"Scheduler class to use (default: nil). Provide blank or true to use Itsi::Scheduler, or a classname to use an alternative scheduler") do |scheduler_class|
|
62
63
|
if scheduler_class.nil? || scheduler_class == "true"
|
63
64
|
options[:scheduler_class] = "Itsi::Scheduler"
|
@@ -154,7 +155,6 @@ if ENV['COMP_LINE'] || ARGV.include?('--completion')
|
|
154
155
|
end
|
155
156
|
|
156
157
|
parser.parse!
|
157
|
-
|
158
158
|
case (command = ARGV.shift)
|
159
159
|
when *COMMANDS.keys
|
160
160
|
required_arity = Itsi::Server.method(command).parameters&.select{|c| c.first == :req }&.length&.succ || 2
|
@@ -0,0 +1,86 @@
|
|
1
|
+
[package]
|
2
|
+
name = "itsi_acme"
|
3
|
+
version = "0.1.0"
|
4
|
+
authors = [
|
5
|
+
"wouterkem <wc@pico.net.nz>",
|
6
|
+
"dignifiedquire <me@dignifiedquire.com>",
|
7
|
+
"Florian Uekermann <florian@uekermann.me>",
|
8
|
+
]
|
9
|
+
edition = "2018"
|
10
|
+
description = "Automatic TLS certificate management using rustls, specifically for itsi"
|
11
|
+
license = "Apache-2.0 OR MIT"
|
12
|
+
repository = "https://github.com/n0-computer/tokio-rustls-acme"
|
13
|
+
documentation = "https://docs.rs/tokio-rustls-acme"
|
14
|
+
keywords = ["acme", "rustls", "tls", "letsencrypt"]
|
15
|
+
categories = ["asynchronous", "cryptography", "network-programming"]
|
16
|
+
|
17
|
+
[dependencies]
|
18
|
+
futures = "0.3.21"
|
19
|
+
rcgen = "0.13"
|
20
|
+
serde_json = "1.0.81"
|
21
|
+
serde = { version = "1.0.137", features = ["derive"] }
|
22
|
+
ring = { version = "0.17.0", features = ["std"] }
|
23
|
+
base64 = "0.22"
|
24
|
+
log = "0.4.17"
|
25
|
+
webpki-roots = "0.26"
|
26
|
+
pem = "3.0"
|
27
|
+
thiserror = "2.0"
|
28
|
+
x509-parser = "0.16"
|
29
|
+
chrono = { version = "0.4.24", default-features = false, features = ["clock"] }
|
30
|
+
async-trait = "0.1.53"
|
31
|
+
rustls = { version = "0.23", default-features = false, features = ["ring"] }
|
32
|
+
time = "0.3.36" # force the transitive dependency to a more recent minimal version. The build fails with 0.3.20
|
33
|
+
|
34
|
+
tokio = { version = "1.20.1", default-features = false }
|
35
|
+
tokio-rustls = { version = "0.26", default-features = false, features = [
|
36
|
+
"tls12",
|
37
|
+
] }
|
38
|
+
reqwest = { version = "0.12", default-features = false, features = [
|
39
|
+
"rustls-tls",
|
40
|
+
] }
|
41
|
+
|
42
|
+
# Axum
|
43
|
+
axum-server = { version = "0.7", features = ["tokio-rustls"], optional = true }
|
44
|
+
|
45
|
+
[dependencies.proc-macro2]
|
46
|
+
# This is a transitive dependency, we specify it to make sure we have
|
47
|
+
# a recent-enough version so that -Z minimal-versions crate resolution
|
48
|
+
# works.
|
49
|
+
version = "1.0.78"
|
50
|
+
|
51
|
+
[dependencies.num-bigint]
|
52
|
+
# This is a transitive dependency, we specify it to make sure we have
|
53
|
+
# a recent-enough version so that -Z minimal-versions crate resolution
|
54
|
+
# works.
|
55
|
+
version = "0.4.4"
|
56
|
+
|
57
|
+
[dev-dependencies]
|
58
|
+
simple_logger = "5.0"
|
59
|
+
structopt = "0.3.26"
|
60
|
+
clap = { version = "4", features = ["derive"] }
|
61
|
+
axum = "0.7"
|
62
|
+
tokio = { version = "1.19.2", features = ["full"] }
|
63
|
+
tokio-stream = { version = "0.1.9", features = ["net"] }
|
64
|
+
tokio-util = { version = "0.7.3", features = ["compat"] }
|
65
|
+
warp = "0.3"
|
66
|
+
|
67
|
+
[package.metadata.docs.rs]
|
68
|
+
all-features = true
|
69
|
+
rustdoc-args = ["--cfg", "doc_auto_cfg"]
|
70
|
+
|
71
|
+
[features]
|
72
|
+
default = []
|
73
|
+
axum = ["dep:axum-server"]
|
74
|
+
|
75
|
+
[[example]]
|
76
|
+
name = "low_level_axum"
|
77
|
+
required-features = ["axum"]
|
78
|
+
|
79
|
+
[[example]]
|
80
|
+
name = "high_level_warp"
|
81
|
+
|
82
|
+
[[example]]
|
83
|
+
name = "high_level"
|
84
|
+
|
85
|
+
[[example]]
|
86
|
+
name = "low_level"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
use clap::Parser;
|
2
|
+
use itsi_acme::caches::DirCache;
|
3
|
+
use itsi_acme::AcmeConfig;
|
4
|
+
use std::net::Ipv6Addr;
|
5
|
+
use std::path::PathBuf;
|
6
|
+
use tokio::io::AsyncWriteExt;
|
7
|
+
use tokio_stream::wrappers::TcpListenerStream;
|
8
|
+
use tokio_stream::StreamExt;
|
9
|
+
|
10
|
+
#[derive(Parser, Debug)]
|
11
|
+
struct Args {
|
12
|
+
/// Domains
|
13
|
+
#[clap(short, required = true)]
|
14
|
+
domains: Vec<String>,
|
15
|
+
|
16
|
+
/// Contact info
|
17
|
+
#[clap(short)]
|
18
|
+
email: Vec<String>,
|
19
|
+
|
20
|
+
/// Cache directory
|
21
|
+
#[clap(short)]
|
22
|
+
cache: Option<PathBuf>,
|
23
|
+
|
24
|
+
/// Use Let's Encrypt production environment
|
25
|
+
/// (see https://letsencrypt.org/docs/staging-environment/)
|
26
|
+
#[clap(long)]
|
27
|
+
prod: bool,
|
28
|
+
|
29
|
+
#[clap(short, long, default_value = "443")]
|
30
|
+
port: u16,
|
31
|
+
}
|
32
|
+
|
33
|
+
#[tokio::main]
|
34
|
+
async fn main() {
|
35
|
+
simple_logger::init_with_level(log::Level::Info).unwrap();
|
36
|
+
let args = Args::parse();
|
37
|
+
|
38
|
+
let tcp_listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, args.port))
|
39
|
+
.await
|
40
|
+
.unwrap();
|
41
|
+
let tcp_incoming = TcpListenerStream::new(tcp_listener);
|
42
|
+
|
43
|
+
let mut tls_incoming = AcmeConfig::new(args.domains)
|
44
|
+
.contact(args.email.iter().map(|e| format!("mailto:{}", e)))
|
45
|
+
.cache_option(args.cache.clone().map(DirCache::new))
|
46
|
+
.directory_lets_encrypt(args.prod)
|
47
|
+
.incoming(tcp_incoming, Vec::new());
|
48
|
+
|
49
|
+
while let Some(tls) = tls_incoming.next().await {
|
50
|
+
let mut tls = tls.unwrap();
|
51
|
+
tokio::spawn(async move {
|
52
|
+
tls.write_all(HELLO).await.unwrap();
|
53
|
+
tls.shutdown().await.unwrap();
|
54
|
+
});
|
55
|
+
}
|
56
|
+
unreachable!()
|
57
|
+
}
|
58
|
+
|
59
|
+
const HELLO: &[u8] = br#"HTTP/1.1 200 OK
|
60
|
+
Content-Length: 10
|
61
|
+
Content-Type: text/plain; charset=utf-8
|
62
|
+
|
63
|
+
Hello Tls!"#;
|
@@ -0,0 +1,52 @@
|
|
1
|
+
use clap::Parser;
|
2
|
+
use itsi_acme::caches::DirCache;
|
3
|
+
use itsi_acme::AcmeConfig;
|
4
|
+
use std::net::Ipv6Addr;
|
5
|
+
use std::path::PathBuf;
|
6
|
+
use tokio_stream::wrappers::TcpListenerStream;
|
7
|
+
use warp::Filter;
|
8
|
+
|
9
|
+
#[derive(Parser, Debug)]
|
10
|
+
struct Args {
|
11
|
+
/// Domains
|
12
|
+
#[clap(short, required = true)]
|
13
|
+
domains: Vec<String>,
|
14
|
+
|
15
|
+
/// Contact info
|
16
|
+
#[clap(short)]
|
17
|
+
email: Vec<String>,
|
18
|
+
|
19
|
+
/// Cache directory
|
20
|
+
#[clap(short)]
|
21
|
+
cache: Option<PathBuf>,
|
22
|
+
|
23
|
+
/// Use Let's Encrypt production environment
|
24
|
+
/// (see https://letsencrypt.org/docs/staging-environment/)
|
25
|
+
#[clap(long)]
|
26
|
+
prod: bool,
|
27
|
+
|
28
|
+
#[clap(short, long, default_value = "443")]
|
29
|
+
port: u16,
|
30
|
+
}
|
31
|
+
|
32
|
+
#[tokio::main]
|
33
|
+
async fn main() {
|
34
|
+
simple_logger::init_with_level(log::Level::Info).unwrap();
|
35
|
+
let args = Args::parse();
|
36
|
+
|
37
|
+
let tcp_listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, args.port))
|
38
|
+
.await
|
39
|
+
.unwrap();
|
40
|
+
let tcp_incoming = TcpListenerStream::new(tcp_listener);
|
41
|
+
|
42
|
+
let tls_incoming = AcmeConfig::new(args.domains)
|
43
|
+
.contact(args.email.iter().map(|e| format!("mailto:{}", e)))
|
44
|
+
.cache_option(args.cache.clone().map(DirCache::new))
|
45
|
+
.directory_lets_encrypt(args.prod)
|
46
|
+
.incoming(tcp_incoming, Vec::new());
|
47
|
+
|
48
|
+
let route = warp::any().map(|| "Hello Tls!");
|
49
|
+
warp::serve(route).run_incoming(tls_incoming).await;
|
50
|
+
|
51
|
+
unreachable!()
|
52
|
+
}
|
@@ -0,0 +1,87 @@
|
|
1
|
+
use clap::Parser;
|
2
|
+
use itsi_acme::caches::DirCache;
|
3
|
+
use itsi_acme::{AcmeAcceptor, AcmeConfig};
|
4
|
+
use rustls::ServerConfig;
|
5
|
+
use std::net::Ipv6Addr;
|
6
|
+
use std::path::PathBuf;
|
7
|
+
use std::sync::Arc;
|
8
|
+
use tokio::io::AsyncWriteExt;
|
9
|
+
use tokio_stream::StreamExt;
|
10
|
+
|
11
|
+
#[derive(Parser, Debug)]
|
12
|
+
struct Args {
|
13
|
+
/// Domains
|
14
|
+
#[clap(short, required = true)]
|
15
|
+
domains: Vec<String>,
|
16
|
+
|
17
|
+
/// Contact info
|
18
|
+
#[clap(short)]
|
19
|
+
email: Vec<String>,
|
20
|
+
|
21
|
+
/// Cache directory
|
22
|
+
#[clap(short)]
|
23
|
+
cache: Option<PathBuf>,
|
24
|
+
|
25
|
+
/// Use Let's Encrypt production environment
|
26
|
+
/// (see https://letsencrypt.org/docs/staging-environment/)
|
27
|
+
#[clap(long)]
|
28
|
+
prod: bool,
|
29
|
+
|
30
|
+
#[clap(short, long, default_value = "443")]
|
31
|
+
port: u16,
|
32
|
+
}
|
33
|
+
|
34
|
+
#[tokio::main]
|
35
|
+
async fn main() {
|
36
|
+
simple_logger::init_with_level(log::Level::Info).unwrap();
|
37
|
+
let args = Args::parse();
|
38
|
+
|
39
|
+
let mut state = AcmeConfig::new(args.domains)
|
40
|
+
.contact(args.email.iter().map(|e| format!("mailto:{}", e)))
|
41
|
+
.cache_option(args.cache.clone().map(DirCache::new))
|
42
|
+
.directory_lets_encrypt(args.prod)
|
43
|
+
.state();
|
44
|
+
let rustls_config = ServerConfig::builder()
|
45
|
+
.with_no_client_auth()
|
46
|
+
.with_cert_resolver(state.resolver());
|
47
|
+
let acceptor = state.acceptor();
|
48
|
+
|
49
|
+
tokio::spawn(async move {
|
50
|
+
loop {
|
51
|
+
match state.next().await.unwrap() {
|
52
|
+
Ok(ok) => log::info!("event: {:?}", ok),
|
53
|
+
Err(err) => log::error!("error: {:?}", err),
|
54
|
+
}
|
55
|
+
}
|
56
|
+
});
|
57
|
+
|
58
|
+
serve(acceptor, Arc::new(rustls_config), args.port).await;
|
59
|
+
}
|
60
|
+
|
61
|
+
async fn serve(acceptor: AcmeAcceptor, rustls_config: Arc<ServerConfig>, port: u16) {
|
62
|
+
let listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, port))
|
63
|
+
.await
|
64
|
+
.unwrap();
|
65
|
+
loop {
|
66
|
+
let tcp = listener.accept().await.unwrap().0;
|
67
|
+
let rustls_config = rustls_config.clone();
|
68
|
+
let accept_future = acceptor.accept(tcp);
|
69
|
+
|
70
|
+
tokio::spawn(async move {
|
71
|
+
match accept_future.await.unwrap() {
|
72
|
+
None => log::info!("received TLS-ALPN-01 validation request"),
|
73
|
+
Some(start_handshake) => {
|
74
|
+
let mut tls = start_handshake.into_stream(rustls_config).await.unwrap();
|
75
|
+
tls.write_all(HELLO).await.unwrap();
|
76
|
+
tls.shutdown().await.unwrap();
|
77
|
+
}
|
78
|
+
}
|
79
|
+
});
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
const HELLO: &[u8] = br#"HTTP/1.1 200 OK
|
84
|
+
Content-Length: 10
|
85
|
+
Content-Type: text/plain; charset=utf-8
|
86
|
+
|
87
|
+
Hello Tls!"#;
|
@@ -0,0 +1,66 @@
|
|
1
|
+
use axum::{routing::get, Router};
|
2
|
+
use clap::Parser;
|
3
|
+
use itsi_acme::caches::DirCache;
|
4
|
+
use itsi_acme::AcmeConfig;
|
5
|
+
use rustls::ServerConfig;
|
6
|
+
use std::net::{Ipv6Addr, SocketAddr};
|
7
|
+
use std::path::PathBuf;
|
8
|
+
use std::sync::Arc;
|
9
|
+
use tokio_stream::StreamExt;
|
10
|
+
|
11
|
+
#[derive(Parser, Debug)]
|
12
|
+
struct Args {
|
13
|
+
/// Domains
|
14
|
+
#[clap(short, required = true)]
|
15
|
+
domains: Vec<String>,
|
16
|
+
|
17
|
+
/// Contact info
|
18
|
+
#[clap(short)]
|
19
|
+
email: Vec<String>,
|
20
|
+
|
21
|
+
/// Cache directory
|
22
|
+
#[clap(short)]
|
23
|
+
cache: Option<PathBuf>,
|
24
|
+
|
25
|
+
/// Use Let's Encrypt production environment
|
26
|
+
/// (see https://letsencrypt.org/docs/staging-environment/)
|
27
|
+
#[clap(long)]
|
28
|
+
prod: bool,
|
29
|
+
|
30
|
+
#[clap(short, long, default_value = "443")]
|
31
|
+
port: u16,
|
32
|
+
}
|
33
|
+
|
34
|
+
#[tokio::main]
|
35
|
+
async fn main() {
|
36
|
+
simple_logger::init_with_level(log::Level::Info).unwrap();
|
37
|
+
let args = Args::parse();
|
38
|
+
|
39
|
+
let mut state = AcmeConfig::new(args.domains)
|
40
|
+
.contact(args.email.iter().map(|e| format!("mailto:{}", e)))
|
41
|
+
.cache_option(args.cache.clone().map(DirCache::new))
|
42
|
+
.directory_lets_encrypt(args.prod)
|
43
|
+
.state();
|
44
|
+
let rustls_config = ServerConfig::builder()
|
45
|
+
.with_no_client_auth()
|
46
|
+
.with_cert_resolver(state.resolver());
|
47
|
+
let acceptor = state.axum_acceptor(Arc::new(rustls_config));
|
48
|
+
|
49
|
+
tokio::spawn(async move {
|
50
|
+
loop {
|
51
|
+
match state.next().await.unwrap() {
|
52
|
+
Ok(ok) => log::info!("event: {:?}", ok),
|
53
|
+
Err(err) => log::error!("error: {:?}", err),
|
54
|
+
}
|
55
|
+
}
|
56
|
+
});
|
57
|
+
|
58
|
+
let app = Router::new().route("/", get(|| async { "Hello Tls!" }));
|
59
|
+
|
60
|
+
let addr = SocketAddr::from((Ipv6Addr::UNSPECIFIED, args.port));
|
61
|
+
axum_server::bind(addr)
|
62
|
+
.acceptor(acceptor)
|
63
|
+
.serve(app.into_make_service())
|
64
|
+
.await
|
65
|
+
.unwrap();
|
66
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
use crate::acme::ACME_TLS_ALPN_NAME;
|
2
|
+
use crate::ResolvesServerCertAcme;
|
3
|
+
use rustls::server::Acceptor;
|
4
|
+
use rustls::ServerConfig;
|
5
|
+
use std::future::Future;
|
6
|
+
use std::io;
|
7
|
+
use std::pin::Pin;
|
8
|
+
use std::sync::Arc;
|
9
|
+
use std::task::{Context, Poll};
|
10
|
+
use tokio::io::{AsyncRead, AsyncWrite};
|
11
|
+
use tokio_rustls::{Accept, LazyConfigAcceptor, StartHandshake};
|
12
|
+
|
13
|
+
#[derive(Clone)]
|
14
|
+
pub struct AcmeAcceptor {
|
15
|
+
config: Arc<ServerConfig>,
|
16
|
+
}
|
17
|
+
|
18
|
+
impl AcmeAcceptor {
|
19
|
+
pub(crate) fn new(resolver: Arc<ResolvesServerCertAcme>) -> Self {
|
20
|
+
let mut config = ServerConfig::builder()
|
21
|
+
.with_no_client_auth()
|
22
|
+
.with_cert_resolver(resolver);
|
23
|
+
config.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
|
24
|
+
Self {
|
25
|
+
config: Arc::new(config),
|
26
|
+
}
|
27
|
+
}
|
28
|
+
pub fn accept<IO: AsyncRead + AsyncWrite + Unpin>(&self, io: IO) -> AcmeAccept<IO> {
|
29
|
+
AcmeAccept::new(io, self.config.clone())
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
pub struct AcmeAccept<IO: AsyncRead + AsyncWrite + Unpin> {
|
34
|
+
acceptor: LazyConfigAcceptor<IO>,
|
35
|
+
config: Arc<ServerConfig>,
|
36
|
+
validation_accept: Option<Accept<IO>>,
|
37
|
+
}
|
38
|
+
|
39
|
+
impl<IO: AsyncRead + AsyncWrite + Unpin> AcmeAccept<IO> {
|
40
|
+
pub(crate) fn new(io: IO, config: Arc<ServerConfig>) -> Self {
|
41
|
+
Self {
|
42
|
+
acceptor: LazyConfigAcceptor::new(Acceptor::default(), io),
|
43
|
+
config,
|
44
|
+
validation_accept: None,
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
impl<IO: AsyncRead + AsyncWrite + Unpin> Future for AcmeAccept<IO> {
|
50
|
+
type Output = io::Result<Option<StartHandshake<IO>>>;
|
51
|
+
|
52
|
+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
53
|
+
loop {
|
54
|
+
if let Some(validation_accept) = &mut self.validation_accept {
|
55
|
+
return match Pin::new(validation_accept).poll(cx) {
|
56
|
+
Poll::Ready(Ok(_)) => Poll::Ready(Ok(None)),
|
57
|
+
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
|
58
|
+
Poll::Pending => Poll::Pending,
|
59
|
+
};
|
60
|
+
}
|
61
|
+
|
62
|
+
return match Pin::new(&mut self.acceptor).poll(cx) {
|
63
|
+
Poll::Ready(Ok(handshake)) => {
|
64
|
+
let is_validation = handshake
|
65
|
+
.client_hello()
|
66
|
+
.alpn()
|
67
|
+
.into_iter()
|
68
|
+
.flatten()
|
69
|
+
.eq([ACME_TLS_ALPN_NAME]);
|
70
|
+
if is_validation {
|
71
|
+
self.validation_accept = Some(handshake.into_stream(self.config.clone()));
|
72
|
+
continue;
|
73
|
+
}
|
74
|
+
Poll::Ready(Ok(Some(handshake)))
|
75
|
+
}
|
76
|
+
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
|
77
|
+
Poll::Pending => Poll::Pending,
|
78
|
+
};
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|