chkdfront 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 56a52ddfb0d5fbbfd69cb1e231bd8e5545d9a7c0467a5a438d1c7783029db7ed
4
+ data.tar.gz: 4187aec0c81896522bcef3a528cdf9057fd5e747209a5ff80fedc367a94093b6
5
+ SHA512:
6
+ metadata.gz: f3f6407453d3ddf42344038bcfa085031d6d6a4192989b6d08c7d19d86238ac73fad971fd7576c5ddbec238a19c3c35a0d3ac1376e3020bae76bea72b3b26eb6
7
+ data.tar.gz: c2e3c72f7efd6079542404911238cd46a6127865c7e3e3a261de699c5800b924b0fed1f74b1a2fd7ae8362019678989e9cc4ebab61fd32c6dc1b27118aa4dc23
data/.gitignore ADDED
@@ -0,0 +1,146 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ ### macOS template
10
+ # General
11
+ .DS_Store
12
+ .AppleDouble
13
+ .LSOverride
14
+
15
+ # Icon must end with two \r
16
+ Icon
17
+
18
+ # Thumbnails
19
+ ._*
20
+
21
+ # Files that might appear in the root of a volume
22
+ .DocumentRevisions-V100
23
+ .fseventsd
24
+ .Spotlight-V100
25
+ .TemporaryItems
26
+ .Trashes
27
+ .VolumeIcon.icns
28
+ .com.apple.timemachine.donotpresent
29
+
30
+ # Directories potentially created on remote AFP share
31
+ .AppleDB
32
+ .AppleDesktop
33
+ Network Trash Folder
34
+ Temporary Items
35
+ .apdisk
36
+ ### Ruby template
37
+ *.gem
38
+ *.rbc
39
+ /.config
40
+ /coverage/
41
+ /InstalledFiles
42
+ /pkg/
43
+ /spec/reports/
44
+ /spec/examples.txt
45
+ /test/tmp/
46
+ /test/version_tmp/
47
+ /tmp/
48
+
49
+ # Used by dotenv library to load environment variables.
50
+ # .env
51
+
52
+ ## Specific to RubyMotion:
53
+ .dat*
54
+ .repl_history
55
+ build/
56
+ *.bridgesupport
57
+ build-iPhoneOS/
58
+ build-iPhoneSimulator/
59
+
60
+ ## Specific to RubyMotion (use of CocoaPods):
61
+ #
62
+ # We recommend against adding the Pods directory to your .gitignore. However
63
+ # you should judge for yourself, the pros and cons are mentioned at:
64
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
65
+ #
66
+ # vendor/Pods/
67
+
68
+ ## Documentation cache and generated files:
69
+ /.yardoc/
70
+ /_yardoc/
71
+ /doc/
72
+ /rdoc/
73
+
74
+ ## Environment normalization:
75
+ /.bundle/
76
+ /vendor/bundle
77
+ /lib/bundler/man/
78
+
79
+ # for a library or gem, you might want to ignore these files since the code is
80
+ # intended to run in multiple environments; otherwise, check them in:
81
+ # Gemfile.lock
82
+ # .ruby-version
83
+ # .ruby-gemset
84
+
85
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
86
+ .rvmrc
87
+ ### JetBrains template
88
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
89
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
90
+
91
+ # User-specific stuff
92
+ .idea/**/workspace.xml
93
+ .idea/**/tasks.xml
94
+ .idea/**/dictionaries
95
+ .idea/**/shelf
96
+
97
+ # Sensitive or high-churn files
98
+ .idea/**/dataSources/
99
+ .idea/**/dataSources.ids
100
+ .idea/**/dataSources.local.xml
101
+ .idea/**/sqlDataSources.xml
102
+ .idea/**/dynamic.xml
103
+ .idea/**/uiDesigner.xml
104
+ .idea/**/dbnavigator.xml
105
+
106
+ # Gradle
107
+ .idea/**/gradle.xml
108
+ .idea/**/libraries
109
+
110
+ # CMake
111
+ cmake-build-debug/
112
+ cmake-build-release/
113
+
114
+ # Mongo Explorer plugin
115
+ .idea/**/mongoSettings.xml
116
+
117
+ # File-based project format
118
+ *.iws
119
+
120
+ # IntelliJ
121
+ out/
122
+
123
+ # mpeltonen/sbt-idea plugin
124
+ .idea_modules/
125
+
126
+ # JIRA plugin
127
+ atlassian-ide-plugin.xml
128
+
129
+ # Cursive Clojure plugin
130
+ .idea/replstate.xml
131
+
132
+ # Crashlytics plugin (for Android Studio and IntelliJ)
133
+ com_crashlytics_export_strings.xml
134
+ crashlytics.properties
135
+ crashlytics-build.properties
136
+ fabric.properties
137
+
138
+ # Editor-based Rest Client
139
+ .idea/httpRequests
140
+ ### VisualStudioCode template
141
+ .vscode/*
142
+ !.vscode/settings.json
143
+ !.vscode/tasks.json
144
+ !.vscode/launch.json
145
+ !.vscode/extensions.json
146
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in chkdfront.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Chkdfront
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/chkdfront`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'chkdfront'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install chkdfront
22
+
23
+ ## Usage
24
+
25
+ ```
26
+ MMMMMMMMMMMMMWNK0kdolc;,'... .;KMMMMMMMMMMMMMMMMMMMMMMMMMMM
27
+ MMMMMMMMMN0xl;'. lNMMMMMMMMMMMMMMMMMMMMMMMMMM
28
+ MMMMMWKxc'. .kWMMMMMMMMMMMMMMMMMMMMMMMMM
29
+ MMN0o;. ;XMMMMMMMMMMMMMMMMMMMMMMMMM
30
+ Ol,. .xWMMMMMMMMMMMMMMMMMMMMMMMM
31
+ ' . ;XMMMMMMMMMMMMMMMMMMMMMMMM
32
+ l .;dO00ko;'. .kMMMMMMMMMMMMMMMMMMMMMMMM
33
+ X: .dKNWWXOl,. oWMMMMMMMMMMMMMMMMMMMMMMM
34
+ M0, 'ldkx; .',,..,;:cc;dNMMMMMMMMMMMMMMMMMMMMMMM
35
+ MWk. .dNMMWk. ;ONWWWWWWMMMMMMMMMMMMMMMMMMMMMMMM
36
+ MMWx. lXXKkc. :XMXOo;;coxOKNWMMMMMMMMMMMMMMMMMMM
37
+ MMMWx. .... ;KMXc. .';cdkKNMMMMMMMMMMMMMM
38
+ MMMMWk. .:oxxkXMNl .,cx0NMMMMMMMMMM
39
+ MMMMMWO, .oXWWXNMMNo. .,lONMMMMMMM
40
+ MMMMMMMXl. .kNOo,;OWWx. 'lONMMMM
41
+ MMMMMMMMWO; .lx;. lNMO' .,dKWM
42
+ MMMMMMMMMMNx;. .. ,0MX: .,:ll:,. .:x
43
+ MMMMMMMMMMMMNOc. .dWWx. .'lXWMNOc. .
44
+ MMMMMMMMMMMMMMWXOo:':KMX: .cxO0k; .o
45
+ MMMMMMMMMMMMMMMMMMWNNWMk. ,odol,. .dN
46
+ MMMMMMMMMMMMMMMMMMMMMMWo .dXWMWO: .dNM
47
+ MMMMMMMMMMMMMMMMMMMMMMNc ;, 'cdxko. .kWMM
48
+ MMMMMMMMMMMMMMMMMMMMMMNc lKOl. ;0WMMM
49
+ MMMMMMMMMMMMMMMMMMMMMMWo ,KMW0l. .lXMMMMM
50
+ MMMMMMMMMMMMMMMMMMMMMMMk. :kKMWXOdolcc:,. ,kWMMMMMM
51
+ MMMMMMMMMMMMMMMMMMMMMMMNc .'o0XNNNKOo;. 'dXMMMMMMMM
52
+ MMMMMMMMMMMMMMMMMMMMMMMMK; ..''.. 'dXWMMMMMMMMM
53
+ MMMMMMMMMMMMMMMMMMMMMMMMMKc .:xXMMMMMMMMMMMM
54
+ MMMMMMMMMMMMMMMMMMMMMMMMMMNk;. .'cxKWMMMMMMMMMMMMMM
55
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMNxl:'....':oOXWMMMMMMMMMMMMMMMMM
56
+
57
+ ```
58
+
59
+ ## Development
60
+
61
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
62
+
63
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
64
+
65
+ ## Contributing
66
+
67
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/chkdfront.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/chkdfront ADDED
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # @Author: KING SABRI - @KINGSABRI
4
+ #
5
+ require 'chkdfront'
6
+
7
+ logo = %Q{
8
+ MMMMMMMMMMMMMWNK0kdolc;,' ;KMMMMMMMMMMMMMMMMMMMMMMMMMMM
9
+ MMMMMMMMMN0xl;'. lNMMMMMMMMMMMMMMMMMMMMMMMMMM
10
+ MMMMMWKxc'. .kWMMMMMMMMMMMMMMMMMMMMMMMMM
11
+ MMN0o;. ;XMMMMMMMMMMMMMMMMMMMMMMMMM
12
+ Ol,. .xWMMMMMMMMMMMMMMMMMMMMMMMM
13
+ ' . ;XMMMMMMMMMMMMMMMMMMMMMMMM
14
+ l .;dO00ko;'. .kMMMMMMMMMMMMMMMMMMMMMMMM
15
+ X: .dKNWWXOl,. oWMMMMMMMMMMMMMMMMMMMMMMM
16
+ M0, 'ldkx; .',,..,;:cc;dNMMMMMMMMMMMMMMMMMMMMMMM
17
+ MWk. .doMaiN. ;ONWWWWWWMMMMMMMMMMMMMMMMMMMMMMMM
18
+ MMWx. lXXKkc. :XMXOo;;coxOKNWMMMMMMMMMMMMMMMMMMM
19
+ MMMWx. .... ;KMXc. .';cdkKNMMMMMMMMMMMMMM
20
+ MMMMWk. .:oxxkXMNl .,cx0NMMMMMMMMMM
21
+ MMMMMWO, .oXWWXNMMNo. .,lONMMMMMMM
22
+ MMMMMMMXl. .kNOo,;OWWx. 'lONMMMM
23
+ MMMMMMMMWO; .lx;. lNMO' .,dKWM
24
+ MMMMMMMMMMNx;. .. ,0MX: .,:ll:,. .:x
25
+ MMMMMMMMMMMMNOc. .dWWx. .'lXWMNOc. .
26
+ MMMMMMMMMMMMMMWXOo:':KMX: .cxO0k; .o
27
+ MMMMMMMMMMMMMMMMMMWNNWMk. ,domain. .N
28
+ MMMMMMMMMMMMMMMMMMMMMMWo .fronting .dNM
29
+ MMMMMMMMMMMMMMMMMMMMMMNc ;, 'cdxko. .kWMM
30
+ MMMMMMMMMMMMMMMMMMMMMMNc lKOl. ;0WMMM
31
+ MMMMMMMMMMMMMMMMMMMMMMWo ,KMW0l. .lXMMMMM
32
+ MMMMMMMMMMMMMMMMMMMMMMMk. :kKMWXOdolcc:,. ,kWMMMMMM
33
+ MMMMMMMMMMMMMMMMMMMMMMMNc .'o0XNNNKOo;. 'dXMMMMMMMM
34
+ MMMMMMMMMMMMMMMMMMMMMMMMK; ..''.. 'dXWMMMMMMMMM
35
+ MM By: #{'@KINGSABRI'.bold} MMMMMMKc .:xXMMMMMMMMMMMM
36
+ MM #{'chkdfront'.bold} v#{ChkDFront::VERSION} MMMMNk;. .'cxKWMMMMMMMMMMMMMM
37
+ MMMMMMMMMMMMMMMMMMMMMMMMMMMMNxl:'....':oOXWMMMMMMMMMMMMMMMMM
38
+ }
39
+
40
+ CLI::UI::StdoutRouter.enable
41
+
42
+ options = OpenStruct.new(
43
+ front_target: nil, domain_front: nil, provider: :auto,
44
+ expect: nil, proxy: nil, debug: false, tshoot: false
45
+ )
46
+ option_parser = OptionParser.new do |opts|
47
+ opts.banner = "Check DomainFront (chkdfront) - A tool verifies domain fronting."
48
+ opts.separator ""
49
+ opts.separator "Help menu:"
50
+
51
+ opts.on("-f", "--front-target URL", "Fronted target domain or URL.", "\te.g. images.businessweek.com") do |o|
52
+ options.front_target = o
53
+ end
54
+
55
+ opts.on("-d", "--domain-front DOMAIN", "DomainFront domain.", "\te.g. df36z1umwj2fze.cloudfront.net") do |o|
56
+ options.domain_front = o
57
+ end
58
+
59
+ opts.on("-e", "--expect STRING", "Expect a given string that indicates success. (case-sensitive)", "\te.g. It works") do |o|
60
+ options.expect = o
61
+ end
62
+
63
+ opts.on("-p", "--provider NUM",
64
+ "Choose CDN / Domain Front Provider:", Integer,
65
+ "\t[0] Auto (default - auto tune request. Extra request to detect)",
66
+ "\t[1] Amazon (tune request for Amazon domain fronting)",
67
+ "\t[2] Azure (tune request for Azure domain fronting)",
68
+ "\t[3] Alibaba (tune request for Alibaba domain fronting)") do |provider|
69
+ case provider.to_i
70
+ when 0
71
+ options.provider = :auto
72
+ when 1
73
+ options.provider = :amazon
74
+ when 2
75
+ options.provider = :azure
76
+ when 3
77
+ options.provider = :alibaba
78
+ else
79
+ puts "[!] Unknown Provider: switching to auto.."
80
+ options.provider = :auto
81
+ end
82
+ end
83
+
84
+ opts.on("-t", "--troubleshoot [DOMAIN]", "Force troubleshooting procedures.",
85
+ "execute troubleshooting procedures(ping, http, nslookup) for all parties",
86
+ "(optional: original domain where CDN forwards, to include in the checks)",
87
+ "\te.g. c2.mydomain.com") do |o|
88
+ options.tshoot = o
89
+ end
90
+
91
+ opts.on("--proxy USER:PASS@HOST:PORT", "Use proxy settings if you're behind proxy.",
92
+ "\te.g. user1:Pass123@localhost:8080") do |o|
93
+ options.proxy = o
94
+ end
95
+
96
+ opts.on("--debug", "Force debugging.",
97
+ "show response's body and low-level request and response debug trace.",
98
+ "(default enabled when test fails.)"
99
+ ) do |o|
100
+ options.debug = o
101
+ end
102
+
103
+ opts.on("-h", "--help", "Show this message.") do
104
+ puts logo
105
+ puts opts
106
+ exit!
107
+ end
108
+
109
+ opts.on_tail "\nUsage:\n" + " #{$PROGRAM_NAME} <OPTIONS>"
110
+ opts.on_tail "Example:"
111
+ opts.on_tail %{ #{$PROGRAM_NAME} -f images.businessweek.com -d df36z1umwj2fze.cloudfront.net}
112
+ opts.on_tail %{ #{$PROGRAM_NAME} -f images.businessweek.com -d df36z1umwj2fze.cloudfront.net --debug -t c2.mysite.com\n\n}
113
+ end
114
+
115
+ begin
116
+ option_parser.parse!(ARGV)
117
+ if (options.front_target || options.domain_front).nil?
118
+ puts option_parser
119
+ end
120
+
121
+ # list of hosts to troubleshoot later
122
+ hosts = [options.front_target, options.domain_front, options.tshoot].compact
123
+ cli = ChkDFront::CliOperations.new
124
+
125
+ if options.front_target && options.domain_front
126
+ spnr_opts = {output: $stdout, clear: true, format: :arrow_pulse, hide_cursor: true}
127
+ spinner = TTY::Spinner.new("[:spinner] please wait!", spnr_opts)
128
+ spinner.auto_spin
129
+
130
+ http = ChkDFront::Request.new(options.front_target, options.domain_front, options.proxy)
131
+ http.send_to(cli.find_provider(options.provider, options.domain_front))
132
+ cli.http = http
133
+ cli.request = http.request
134
+ cli.response = http.response
135
+
136
+ res = http.response
137
+ # if the request succeeded
138
+ if res.code.to_i == 200
139
+ CLI::UI::Frame.open('Request', color: :bold, timing: false) do
140
+ CLI::UI::Frame.open("Response | #{res.message} (#{res.code})", color: :green, timing: false) do
141
+ cli.show_success
142
+ cli.show_expected(options.expect) if options.expect
143
+ cli.show_body; cli.show_debug if options.debug
144
+ end
145
+ end
146
+ # if the user want to troubleshoot even request has succeeded
147
+ if options.tshoot || options.tshoot.nil?
148
+ CLI::UI::Frame.open('Troubleshooting'.bold, color: :magenta, timing: false) do
149
+ cli.troubleshoot(hosts)
150
+ end
151
+ end
152
+ else # If request failed, troubleshoot
153
+ CLI::UI::Frame.open('Request', color: :bold, timing: false) do
154
+ CLI::UI::Frame.open("Response | #{res.message} (#{res.code})", color: :red, timing: false) do
155
+ cli.show_checks
156
+ cli.show_body
157
+ cli.show_debug
158
+ end
159
+ end
160
+ CLI::UI::Frame.open('Troubleshooting', color: :magenta, timing: false) { cli.troubleshoot(hosts) }
161
+ end
162
+ end
163
+ rescue OptionParser::MissingArgument => e
164
+ puts option_parser
165
+ e.args.each {|arg| puts '[!] '+ "#{e.reason.capitalize} for '#{arg}' option."}
166
+ rescue OptionParser::InvalidOption => e
167
+ puts option_parser
168
+ pp e
169
+ rescue Exception => e
170
+ puts "#{$PROGRAM_NAME} Exception".error
171
+ puts e.backtrace_locations
172
+ puts e
173
+ end
data/chkdfront.gemspec ADDED
@@ -0,0 +1,38 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "chkdfront/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'chkdfront'
8
+ spec.version = ChkDFront::VERSION
9
+ spec.authors = ['@KINGSABRI']
10
+ spec.email = ['king.sabri@gmail.com']
11
+
12
+ spec.summary = %q{Check Domain Fronting (chkdfront) - It checks if domain fronting is working.}
13
+ spec.description = %q{Check Domain Fronting (chkdfront) - It checks if domain fronting implementation is working.}
14
+ spec.homepage = 'https://github.com/KINGSABRI/chkdfront'
15
+ spec.licenses = ['MIT']
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+
23
+ spec.executables = ['chkdfront']
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency 'cli-ui'
27
+ spec.add_dependency 'tty-spinner'
28
+ spec.add_dependency 'word_wrap'
29
+ spec.add_dependency 'net-ping'
30
+ spec.add_dependency 'net-dns'
31
+ spec.add_dependency 'adomain'
32
+
33
+ spec.add_development_dependency "bundler", "~> 2.0"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+
36
+ spec.metadata['source_code_uri'] = 'https://github.com/KINGSABRI/chkdfront'
37
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/KINGSABRI/chkdfront/issues'
38
+ end
@@ -0,0 +1,126 @@
1
+ class String
2
+ def red; colorize(self, "\e[1m\e[31m"); end
3
+ def green; colorize(self, "\e[1m\e[32m"); end
4
+ def dark_green; colorize(self, "\e[32m"); end
5
+ def yellow; colorize(self, "\e[1m\e[33m"); end
6
+ def blue; colorize(self, "\e[1m\e[34m"); end
7
+ def dark_blue; colorize(self, "\e[34m"); end
8
+ def purple; colorize(self, "\e[35m"); end
9
+ def dark_purple; colorize(self, "\e[1;35m"); end
10
+ def cyan; colorize(self, "\e[1;36m"); end
11
+ def dark_cyan; colorize(self, "\e[36m"); end
12
+ def pure; colorize(self, "\e[0m\e[28m"); end
13
+ def bold; colorize(self, "\e[1m"); end
14
+ def error; colorize(self, "\n[" + " ✖ ".red + "] "); end
15
+ def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
16
+ end
17
+
18
+ module ChkDFront
19
+ class CliOperations
20
+ include ChkDFront::Providers
21
+ attr_accessor :http, :request, :response
22
+ def initialize
23
+ @http = nil
24
+ @request = nil
25
+ @response = nil
26
+
27
+ @regx_domain = /^(?:https?:\/\/)?(?:[^@\n]+@)?([^:\/\n?]+)/ # extract domain from url
28
+ @options = { output: $stdout, format: :pulse_2, success_mark: " ✔ ".green, error_mark: " ✖ ".red, hide_cursor: true }
29
+ end
30
+
31
+ def show_success
32
+ puts CLI::UI.fmt "{{v}} Front target: " + "#{@http.front_target.host}"
33
+ puts CLI::UI.fmt "{{v}} Provider header: " + "#{@response['Via']}"
34
+ puts CLI::UI.fmt "{{v}} Domain front: " + "#{@http.domain_front}"
35
+ end
36
+
37
+ def show_expected(string)
38
+ CLI::UI::Frame.divider('Expected String')
39
+ if @response.body.include?(string)
40
+ puts CLI::UI.fmt "{{v}} Found: " + "#{string}"
41
+ else
42
+ puts CLI::UI.fmt "{{x}} Not Found: " + "#{string}"
43
+ end
44
+ end
45
+
46
+ def show_checks
47
+ puts @http.res_err[:checks]
48
+ end
49
+
50
+ def show_body
51
+ CLI::UI::Frame.divider('Response Body')
52
+ puts @response.body
53
+ end
54
+ def show_debug
55
+ CLI::UI::Frame.divider('Debugging')
56
+ puts WordWrap.ww(@http.debug_output, CLI::UI::Terminal.width)
57
+ end
58
+
59
+ # Find provider if not given by the user
60
+ # @param [Symbol] provider_name
61
+ # given by 'options.provider' option.
62
+ # Default is :auto, accepted is :amazon, :azure, :alibaba
63
+ # @param [String] domain_front
64
+ # given by 'options.domain_front' option.
65
+ def find_provider(provider_name, domain_front)
66
+ @options[:format] = :dots_9
67
+ spinner = TTY::Spinner.new("[:spinner] Auto-detecting", @options)
68
+ case provider_name
69
+ when :auto
70
+ domain = Adomain.domain(domain_front)
71
+ [amazon, azure, alibaba].map do |provider|
72
+ if provider[:dfront].include?(domain)
73
+ # spinner.update(title: "Provider found: #{provider[:name].bold}")
74
+ # spinner.reset
75
+ spinner.success(" | Provider found: #{provider[:name].bold}")
76
+ return provider[:name].downcase.to_sym
77
+ end
78
+ end
79
+ when :amazon || :azure || :alibaba
80
+ provider_name
81
+ else
82
+ spinner.error("Failed to auto detect provider: please use '-p' and choose from: 1, 2 or 3")
83
+ end
84
+ end
85
+
86
+ def troubleshoot(hosts = [])
87
+ icmp_ping hosts
88
+ http_ping hosts
89
+ dns_ping hosts
90
+ end
91
+
92
+ def icmp_ping(hosts)
93
+ CLI::UI::Frame.divider('ICMP Ping', color: :reset)
94
+ hosts.map do |host|
95
+ host = host.scan(@regx_domain).join
96
+ spinner = TTY::Spinner.new("[:spinner] pinging #{host}", @options)
97
+ icmp = ChkDFront::Troubleshoot.icmp_ping(host)
98
+ icmp.ping? ? spinner.success : spinner.error
99
+ end
100
+ end
101
+
102
+ def http_ping(hosts)
103
+ CLI::UI::Frame.divider('HTTP Ping', color: :reset)
104
+ hosts.map do |host|
105
+ host = host.scan(@regx_domain).join
106
+ spinner = TTY::Spinner.new("[:spinner] pinging #{host}", @options)
107
+ http = ChkDFront::Troubleshoot.http_ping(host)
108
+ http.ping? ? spinner.success : spinner.error
109
+ puts http.exception unless http.ping?
110
+ end
111
+ end
112
+
113
+ def dns_ping(hosts)
114
+ CLI::UI::Frame.divider('NSlookup (CNAME)', color: :reset)
115
+ hosts.map do |host|
116
+ host = host.scan(@regx_domain).join
117
+ spinner = TTY::Spinner.new("[:spinner] nslookup #{host}", @options)
118
+ dns = ChkDFront::Troubleshoot.dns_ping(host)
119
+ dns.empty? ? spinner.error : spinner.success
120
+ puts dns
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+
@@ -0,0 +1,68 @@
1
+ module ChkDFront
2
+ # This module contains CDN provider specific settings headers.
3
+ module Providers
4
+ def get_provider(provider, domain_front)
5
+ if domain_front.port
6
+ host = "#{domain_front.host}:#{domain_front.port}"
7
+ else
8
+ host = domain_front.host
9
+ end
10
+ case provider
11
+ when :amazon then amazon(host)
12
+ when :azure then azure(host)
13
+ when :alibaba then alibaba(host)
14
+ else
15
+ puts "Unknown Provider!!!!: #{provider}"
16
+ return false
17
+ end
18
+ end
19
+
20
+ # Amazon vendor specific settings and headers
21
+ # @param [String] host
22
+ # @return [Hash]
23
+ # Returns a hash of { dfront: [domain1, domain2], headers: {}}
24
+ def amazon(host='')
25
+ {
26
+ name: 'Amazon',
27
+ dfront: ['cloudfront.net'],
28
+ headers: {
29
+ 'Host' => host,
30
+ 'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0",
31
+ 'Connection' => 'close'
32
+ }
33
+ }
34
+ end
35
+
36
+ # Azure vendor specific settings and headers
37
+ # @param [String] host
38
+ # @return [Hash]
39
+ # Returns a hash of { dfront: [domain1, domain2], headers: {}}
40
+ def azure(host='')
41
+ {
42
+ name: 'Azure',
43
+ dfront: ['azureedge.net'],
44
+ headers: {
45
+ 'Host' => host,
46
+ 'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0",
47
+ 'Connection' => 'close'
48
+ }
49
+ }
50
+ end
51
+
52
+ # Alibaba vendor specific settings and headers
53
+ # @param [String] host
54
+ # @return [Hash]
55
+ # Returns a hash of { dfront: [domain1, domain2], headers: {}}
56
+ def alibaba(host='')
57
+ {
58
+ name: 'Alibaba',
59
+ dfront: ['kunlungr.com'],
60
+ headers: {
61
+ 'Host' => host,
62
+ 'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0",
63
+ 'Connection' => 'close'
64
+ }
65
+ }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,179 @@
1
+ module ChkDFront
2
+ # Contains all HTTP request related functionalities
3
+ class Request
4
+ include ChkDFront::Providers
5
+
6
+ # @attribute [r] front_target
7
+ # @return [String] front_target
8
+ attr_reader :front_target
9
+ # @!attribute [r] domain_front
10
+ # @return [String]
11
+ attr_reader :domain_front
12
+ # @!attribute [r] proxy
13
+ # @return [String]
14
+ attr_reader :proxy
15
+ # @!attribute [r]
16
+ # @return [String]
17
+ attr_reader :debug_output
18
+ # @!attribute [r] request
19
+ # @return [Net::HTTP::Request]
20
+ attr_reader :request
21
+ # @!attribute [r] request
22
+ # @return [Net::HTTP::Response]
23
+ attr_reader :response
24
+ # @!attribute [r] res_err
25
+ # @return [Hash]
26
+ attr_reader :res_err
27
+
28
+ def initialize(front_target, domain_front, proxy)
29
+ @front_target = format_front_target(front_target)
30
+ @domain_front = format_domain_front(domain_front)
31
+ @proxy = format_proxy(proxy)
32
+ @http = setup_http
33
+ end
34
+
35
+ # Send GET/POST request to the targeted domain
36
+ #
37
+ # @param [Symbol] provider_name
38
+ # Available providers symbols:
39
+ # - :amazon
40
+ # - :azure
41
+ # - :alibaba
42
+ # @param [String] http_method
43
+ # @return [Object]
44
+ def send_to(provider_name, http_method='get')
45
+ provider = get_provider(provider_name, @domain_front)
46
+ @request = Net::HTTP.const_get(http_method.capitalize).new(
47
+ @front_target.request_uri, provider[:headers]
48
+ )
49
+ @response = @http.request(@request)
50
+ check_http(@response) # if response failed, give the user some suggestion
51
+ rescue SocketError => e
52
+ puts "#{self.class}##{__method__}:".error
53
+ puts e.message
54
+ rescue Net::ReadTimeout => e
55
+ puts "#{self.class}##{__method__}:".error
56
+ puts e.message
57
+ puts "Remote port is closed.".error
58
+ exit!
59
+ rescue Exception => e
60
+ puts "#{self.class}##{__method__}:".error
61
+ puts e.full_message
62
+ end
63
+
64
+ private
65
+
66
+ # @param [String] front_target
67
+ # The domain of fronted domain (e.g. images.businessweek.com)
68
+ # This domain should be on the same CDN that user already uses
69
+ # @return [OpenStruct]
70
+ def format_front_target(front_target)
71
+ front_target = "http://#{front_target}" unless front_target.match(/^(http|https):\/\//i)
72
+ uri = URI.parse(front_target)
73
+ OpenStruct.new(host: uri.host, port: uri.port, scheme: uri.scheme, request_uri: uri.request_uri)
74
+ end
75
+
76
+ # @param [String] domain_front
77
+ # The CDN's domain front (e.g. df36z1umwj2fze.cloudfront.net)
78
+ # this domain is what the users create by their provider.
79
+ # @return [String]
80
+ def format_domain_front(domain_front)
81
+ # if the user gave a URL instead a FQDN:PORT, parse it
82
+ # Otherwise just use what you get
83
+ uri = URI.parse(domain_front)
84
+ if uri.scheme
85
+ OpenStruct.new(host: uri.host, port: uri.port)
86
+ else
87
+ host, port = domain_front.split(':')
88
+ OpenStruct.new(host: host, port: port)
89
+ end
90
+ end
91
+
92
+ #
93
+ # @param [String] proxy
94
+ # The accepted proxy format is:
95
+ # - Username and Password separated by column
96
+ # - Hostname and Port separated by column
97
+ # - Both above parts separated by @ sign
98
+ # @example
99
+ # user1:Pass123@localhost:8080
100
+ #
101
+ # @return [OpenStruct]
102
+ def format_proxy(proxy)
103
+ if proxy
104
+ p_url, p_creds = proxy.reverse&.split('@', 2).map(&:reverse)
105
+ p_host, p_port = p_url.split(':') if p_url
106
+ p_user, p_pass = p_creds.split(':', 2) if p_creds
107
+ end
108
+ OpenStruct.new(host: p_host, port: p_port, user: p_user, pass: p_pass)
109
+ end
110
+
111
+ # @private
112
+ # Setups the initial http connection settings.
113
+ # The @!method #send_to is going to use it later
114
+ # @return [Net::HTTP]
115
+ def setup_http
116
+ http = Net::HTTP.new(@front_target.host, @front_target.port,
117
+ @proxy.host, @proxy.port,
118
+ @proxy.user, @proxy.pass)
119
+ http.use_ssl = true if @front_target.scheme =~ /https/i
120
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
121
+ http.open_timeout = 5
122
+ http.read_timeout = 5
123
+ @debug_output = ""
124
+ http.set_debug_output(@debug_output)
125
+ return http
126
+ rescue Exception => e
127
+ puts "#{self.class}##{__method__}:".error
128
+ puts e.full_message
129
+ end
130
+
131
+ # @param [] response
132
+ # HTTP response error-based suggestions.
133
+ # If request fail, it checks the response type and suggest checks based on the error.
134
+ # These suggestion are based on our experience to help users to troubleshoot.
135
+ # If you've faced different cases and responses, please report it us to update the list
136
+ # @todo: move this to a yaml or json file instead
137
+ def check_http(response)
138
+ case response
139
+ when Net::HTTPOK
140
+ response
141
+ when Net::HTTPGatewayTimeOut
142
+ @res_err = {
143
+ orig: response,
144
+ checks: [
145
+ "Check your original server:",
146
+ " is server up?",
147
+ " is service up?",
148
+ " is service port correct?",
149
+ ]
150
+ }
151
+ when Net::HTTPBadGateway
152
+ @res_err = {
153
+ orig: response,
154
+ checks: [
155
+ "- Check your original server:",
156
+ " - is server up?",
157
+ " - is service up?",
158
+ " - is service port correct?",
159
+ "- Check your provider:",
160
+ " - is front domain name correct? (#{@domain_front})",
161
+ " - is destination port correct?.",
162
+ ]
163
+ }
164
+ when Net::HTTPForbidden
165
+ @res_err = {
166
+ orig: response,
167
+ checks: [
168
+ "- Check your provider:",
169
+ " - is front domain name correct? (#{@domain_front})",
170
+ "- Check your target:",
171
+ " - is target domain correct? (#{@front_target.host})",
172
+ " - is target port correct? (#{@front_target.port})"
173
+ ]
174
+ }
175
+ end
176
+ end
177
+ end
178
+ end
179
+
@@ -0,0 +1,22 @@
1
+ module ChkDFront
2
+ # Contains all troubleshooting functionalities.
3
+ # Currently, ping, http, nslookup
4
+ class Troubleshoot
5
+ def self.icmp_ping(host)
6
+ Net::Ping::External.new(host)
7
+ end
8
+
9
+ def self.http_ping(host)
10
+ host = "http://#{host}" unless host.match(/^(http|https):\/\//i)
11
+ Net::Ping::HTTP.new(host)
12
+ end
13
+
14
+ def self.dns_ping(host)
15
+ dns = Net::DNS::Resolver.start(host)
16
+ dns.answer.select {|r| r.type == "CNAME"}&.map(&:cname)
17
+ rescue Exception => e
18
+ puts e.message
19
+ return []
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module ChkDFront
2
+ VERSION = "1.0.1"
3
+ end
data/lib/chkdfront.rb ADDED
@@ -0,0 +1,24 @@
1
+ # Standard libraries
2
+ require 'optparse'
3
+ require 'ostruct'
4
+ require 'net/http'
5
+ require 'openssl'
6
+
7
+ # Chkdfront
8
+ require 'chkdfront/version'
9
+ require 'chkdfront/providers'
10
+ require 'chkdfront/request'
11
+ require 'chkdfront/troubleshoot'
12
+ require 'chkdfront/cli_operations'
13
+
14
+ # External libraries
15
+ require 'cli/ui'
16
+ require 'tty-spinner'
17
+ require 'word_wrap'
18
+ require 'net/ping'
19
+ require 'net/dns'
20
+ require 'adomain'
21
+
22
+ module ChkDFront
23
+ class Error < StandardError; end
24
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chkdfront
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - "@KINGSABRI"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cli-ui
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-spinner
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: word_wrap
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: net-ping
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: net-dns
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: adomain
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '10.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '10.0'
125
+ description: Check Domain Fronting (chkdfront) - It checks if domain fronting implementation
126
+ is working.
127
+ email:
128
+ - king.sabri@gmail.com
129
+ executables:
130
+ - chkdfront
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".gitignore"
135
+ - Gemfile
136
+ - README.md
137
+ - Rakefile
138
+ - bin/chkdfront
139
+ - chkdfront.gemspec
140
+ - lib/chkdfront.rb
141
+ - lib/chkdfront/cli_operations.rb
142
+ - lib/chkdfront/providers.rb
143
+ - lib/chkdfront/request.rb
144
+ - lib/chkdfront/troubleshoot.rb
145
+ - lib/chkdfront/version.rb
146
+ homepage: https://github.com/KINGSABRI/chkdfront
147
+ licenses:
148
+ - MIT
149
+ metadata:
150
+ source_code_uri: https://github.com/KINGSABRI/chkdfront
151
+ bug_tracker_uri: https://github.com/KINGSABRI/chkdfront/issues
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubygems_version: 3.0.2
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Check Domain Fronting (chkdfront) - It checks if domain fronting is working.
171
+ test_files: []