HTTP
Telnet access
GET / HTTP/1.1
host: daveops.net
<line feed>
HTTP response codes
- 1xx Informational
- 2xx Success
- 3xx Redirection
- 4xx Client Error
- 5xx Server Error
| code | status |
|---|---|
| 100 | Continue |
| 101 | Switching Protocols |
| 102 | Processing (WebDAV; RFC 2518) |
| 200 | OK |
| 201 | Created |
| 202 | Accepted |
| 203 | ~Non-Authoritative Information (since HTTP/1.1) |
| 204 | No Content |
| 205 | Reset Content |
| 206 | Partial Content |
| 207 | ~Multi-Status (WebDAV; RFC 4918) |
| 208 | Already Reported (WebDAV; RFC 5842) |
| 226 | IM Used (RFC 3229) |
| 300 | Multiple Choices |
| 301 | Moved Permanently |
| 302 | Found |
| 303 | See Other (since HTTP/1.1) |
| 304 | Not Modified |
| 305 | Use Proxy (since HTTP/1.1) |
| 306 | Switch Proxy |
| 307 | Temporary Redirect (since HTTP/1.1) |
| 308 | Permanent Redirect |
| 400 | Bad Request |
| 401 | Unauthorized |
| 402 | Payment Required |
| 403 | Forbidden |
| 404 | Not Found |
| 405 | Method Not Allowed |
| 406 | Not Acceptable |
| 407 | Proxy Authentication Required |
| 408 | Request Timeout |
| 409 | Conflict |
| 410 | Gone |
| 411 | Length Required |
| 412 | Precondition Failed |
| 413 | Request Entity Too Large |
| 414 | ~Request-URI Too Long |
| 415 | Unsupported Media Type |
| 416 | Requested Range Not Satisfiable |
| 417 | Expectation Failed |
| 418 | I’m a teapot (RFC 2324) |
| 420 | Enhance Your Calm (Twitter) |
| 422 | Unprocessable Entity (WebDAV; RFC 4918) |
| 423 | Locked (WebDAV; RFC 4918) |
| 424 | Failed Dependency (WebDAV; RFC 4918) |
| 424 | Method Failure (WebDAV) |
| 425 | Unordered Collection (Internet draft) |
| 426 | Upgrade Required (RFC 2817) |
| 428 | Precondition Required (RFC 6585) |
| 429 | Too Many Requests (RFC 6585) |
| 431 | Request Header Fields Too Large (RFC 6585) |
| 444 | No Response (Nginx) |
| 449 | Retry With (Microsoft) |
| 450 | Blocked by Windows Parental Controls (Microsoft) |
| 451 | Unavailable For Legal Reasons (Internet draft) |
| 451 | Redirect (Microsoft) |
| 494 | Request Header Too Large (Nginx) |
| 495 | Cert Error (Nginx) |
| 496 | No Cert (Nginx) |
| 497 | HTTP to HTTPS (Nginx) |
| 499 | Client Closed Request (Nginx) |
| 500 | Internal Server Error |
| 501 | Not Implemented |
| 502 | Bad Gateway |
| 503 | Service Unavailable |
| 504 | Gateway Timeout |
| 505 | HTTP Version Not Supported |
| 506 | Variant Also Negotiates (RFC 2295) |
| 507 | Insufficient Storage (WebDAV; RFC 4918) |
| 508 | Loop Detected (WebDAV; RFC 5842) |
| 509 | Bandwidth Limit Exceeded (Apache bw/limited extension) |
| 510 | Not Extended (RFC 2774) |
| 511 | Network Authentication Required (RFC 6585) |
| 598 | Network read timeout error (MS) |
| 599 | Network connect timeout error (MS) |
Apache HTTP Server
- Apache docs
- Mozilla SSL Configuration Generator
- https://httpd.apache.org/docs/current/misc/security_tips.html
- Docker image
Signals
| Signal | Description |
|---|---|
| SIGHUP | Rotate logs, kill children, reload configuration |
| SIGWINCH | Graceful stop |
| SIGUSR1 | Graceful restart |
| SIGTERM | Immediate stop |
Apachectl options
| Option | ShortOption | Description |
|---|---|---|
| start | start daemon | |
| stop | stop daemon | |
| restart | restarts after checking configtest | |
| graceful | graceful restart (checks configtest) | |
| graceful-stop | graceful stop of the daemon | |
| fullstatus | display full status report (modstatus and text browser required) | |
| configtest | -t | test the configuration |
| -S | parse the config, show what IPs are used for virtual hosts |
General Hardening
SSL Config:
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCompression off
# HSTS (mod_headers is required) (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000"
General Apache Config:
# Deny access to root dir
<Directory />
Options None
Order deny,allow
Deny from all
</Directory>
# Disable indexes
Options -Indexes
# Disable server-side includes and CGI scripts
Options -Includes
Options -ExecCGI
# Disable product version
ServerTokens Prod
ServerSignature Off
# Disable TRACE
TraceEnable Off
htaccess
modrewrite
- https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
- https://httpd.apache.org/docs/2.4/rewrite/remapping.html
# Do a redirect that ignores the ACME challenge directory
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge [NC]
RewriteRule ^ https://example.org [L,R=301]
# Redirect to the HTTPS version of the URI
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Allow password protected directories without WordPress 404
RewriteCond %{REQUEST_URI} ^/(failed_auth\.html).*$ [NC]
RewriteRule . - [L]
Do a 301 redirect
RewriteCond %{REQUEST_FILENAME} /tascam688
RewriteCond %{REQUEST_FILENAME} /tascam688/(.*)
RewriteRule (.*) http://www.lonesomecosmonaut.com/2009/tascam-688/ [R=301,L]
Deny hotlinking of images
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?lonesomecosmonaut.com/.*$ [NC]
RewriteRule .(gif|jpg|bmp)$ - [F]
mod_alias
# Redirect all traffic to another domain
RedirectMatch 301 ^(.*)$ https://example.org
# Put website down for maintenance
RedirectMatch 302 ^/ /outoforder.html
Add audio/video handling (HTML 5)
AddType audio/ogg oga ogg
AddType audio/mp3 mp3
AddType video/webm webm
Run Python cgi scripts
(note - scripts should be 755)
Options +ExecCGI
AddHandler cgi-script .py
Do not allow access to .htaccess file
<Files .htaccess>
order allow,deny
deny from all
</Files>
Prevent directory indexing
Options -Indexes
Adding user authentication
<Limit GET PUT POST>
AuthName "Please enter credentials"
AuthType Basic
AuthUserFile /path/personal-htpasswd
Require valid-user
</Limit>
To create an htpasswd file
htpasswd -c .htpasswd username
mod_security
<IfModule security2_module>
# Turn on rule engine and set default action
SecRuleEngine On
SecDefaultAction "phase:2,deny,log,status:403"
</IfModule>
nginx
- https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return
- https://nginx.org/en/docs/http/ngx_http_core_module.html#location
- Docker image
- freenginx (forked from F5)
A funny aside, one of my coworkers said that “nginx is just a hipster Apache”. However, there’s sound technical reasons for choosing nginx called the C10K Problem
Rotate logs
mv access.log access.log.0
kill -USR1 `cat master.nginx.pid`
sleep 1
gzip access.log.0 # do something with access.log.0
Basic TLS config
Check for recent config at https://mozilla.github.io/server-side-tls/ssl-config-generator/
server {
listen 443 ssl;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:5m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /path/to/dhparam.pem;
# Intermediate configuration. tweak to your needs.
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers '<paste intermediate ciphersuite here>';
ssl_prefer_server_ciphers on;
# Enable this if your want HSTS (recommended)
# add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
resolver <IP DNS resolver>;
# ...
}
Redirect only / query
location = / {
# this matches only the / query.
}
Disable nginx version in header
In http, server, or location
server_tokens off
wget
# Mirror a website
wget -mk <site>
curl
# Use client cert
curl --cert client.crt --key client.key URL
# Get the cookie
curl -c JAR ...
# Send the cookie
curl -b JAR ...
# Override referer
curl -e ...
# Send form data with curl
curl -F "key=val" ...
curl -F "uploadedfile=@FILE_TO_UPLOAD;filename=FILENAME_TO_SEND"
# Use POST
curl -X POST -F "url=https://example.org" ..
# Send JSON object
curl -X POST -H "Content-Type: application/json" \
-d '{"name": "admin", "email": "admin@example.com"}' \
https://example.org
# Get request headers
curl -i example.com
# See if server uses gzip/deflate
curl -I -H 'Accept-Encoding: gzip,deflate' http://example.com
Content Security Policy
https://content-security-policy.com/ https://hacks.mozilla.org/2016/02/implementing-content-security-policy/
HAProxy
Setting ciphers on an SSL listener:
bind :443 ssl no-sslv3 crt /path/to/cert.pem ciphers ALL:!EXPORT:!aNULL:!eNULL:!RC4:!MD5:!DES:!3DES:!MEDIUM:!WEAK