Globally disable the HTTP trace method on your web server

Applies to: Apache 2.4

Add the following to your httpd.conf (most common locations are depending on your distribution are /etc/apache2/httpd.conf or /etc/httpd/conf/httpd.conf):

# see: https://httpd.apache.org/docs/2.4/mod/core.html#traceenable
TraceEnable Off

Then restart Apache with sudo systemctl restart httpd.

Once that is done your changes should have been applied to all virtual hosts. We can use curl to verify that our expectation matches the actual result:

$ curl -v -X TRACE --resolve 'cn1-prod.example.cn:80:127.0.0.1' http://cn1-prod.example.cn
* Added cn1-prod.example.cn:80:127.0.0.1 to DNS cache
* Rebuilt URL to: http://cn1-prod.example.cn/
* Hostname was found in DNS cache
*   Trying 127.0.0.1...
* Connected to cn1-prod.example.cn (127.0.0.1) port 80 (#0)
> TRACE / HTTP/1.1
> User-Agent: curl/7.37.0
> Host: cn1-prod.example.cn
> Accept: */*
>
< HTTP/1.1 405 Method Not Allowed
< Date: Mon, 24 Jun 2019 11:59:56 GMT
* Server Apache is not blacklisted
< Server: Apache
< Vary: accept-language,accept-charset
< Accept-Ranges: bytes
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=utf-8
< Content-Language: en
<
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Method not allowed!</title>
<link rev="made" href="mailto:%5bno%20address%20given%5d" />
<style type="text/css"><!--/*--><![CDATA[/*><!--*/
    body { color: #000000; background-color: #FFFFFF; }
    a:link { color: #0000CC; }
    p, address {margin-left: 3em;}
    span {font-size: smaller;}
/*]]>*/--></style>
</head>

<body>
<h1>Method not allowed!</h1>
<p>


    The TRACE
    method is not allowed for the requested URL.

</p>
<p>
If you think this is a server error, please contact
the <a href="mailto:%5bno%20address%20given%5d">webmaster</a>.

</p>

<h2>Error 405</h2>
<address>
  <a href="/">cn1-prod.example.cn</a><br />
  <span>Apache</span>
</address>
</body>
</html>

You might’ve seen that I used the curl option --resolve which helps to query virtual hosts locally. Instead of curl -H 'Host: cn1-prod.example.cn' http://127.0.0.1 I chose to use curl --resolve 'cn1-prod.example.cn:80:127.0.0.1' http://cn1-prod.example.cn.

What’s the difference, you ask?

Among others, this works with HTTPS. Assuming your local server has a certificate for cn1-prod.example.cn, the first example above will fail because the cn1-prod.example.cn certificate doesn’t match the 127.0.0.1 hostname in the URL.

The second example works correctly with HTTPS.

In essence, passing a “Host” header via -H does hack your Host into the header set, but bypasses all of curl’s host-specific intelligence. Using --resolve leverages all of the normal logic that applies, but simply pretends the DNS lookup returned the data in your command-line option. It works just like /etc/hosts should.

Note --resolve takes a port number, so for HTTPS you would use

curl --resolve 'cn1-prod.example.cn:443:127.0.0.1' https://cn1-prod.example.cn/something