{"id":25809,"date":"2015-09-02T21:13:43","date_gmt":"2015-09-02T15:43:43","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=25809"},"modified":"2015-09-10T13:41:02","modified_gmt":"2015-09-10T08:11:02","slug":"selective-blocking-of-curl-and-wget","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/selective-blocking-of-curl-and-wget\/","title":{"rendered":"Selective blocking of curl and wget"},"content":{"rendered":"<p>Wget is a pretty handy tool that lets users download files from any HTTP\/HTTPS or FTP server. Curl, on the other hand is an amazing tool that helps you build a new request with plethora of protocols such as \u00a0HTTP, HTTPS, FTP, Telnet, SMTP etc. These tools can be used to test protocols or your server configurations, but at the same time they can also be misused by a malicious attacker to exploit any website.<\/p>\n<p>In order to thwart these malicious attacks, we need to put specific measures in place. \u00a0One such measure is to block all requests from wget and curl. However, there are specific use cases where you require that external\u00a0users can&#8217;t use these tools but specific IPs or servers can.<\/p>\n<p>So the question is how can we achieve this functionality with Nginx?<\/p>\n<p>One simple way is to block all requests from wget and curl using the sample code given below.<\/p>\n<pre class=\"bash\">### Block wget user agent ###\r\nif ($http_user_agent ~* (wget|curl) ) {\r\n   return 403;\r\n}<\/pre>\n<p>This code block will disallow all requests coming from wget or curl.<\/p>\n<p>In our deployment scenarios, we have some specific servers, which access our website with these tools. Hence, we need a custom solution, where we can\u00a0restrict curl or wget requests from outside network but not from specific servers or IP addresses.<\/p>\n<p>One simple way of achieving this functionality is using Nginx modules. For our solution, we will be using Map and Geo module and some internal variables defined in them.<\/p>\n<p>1. <strong>Map module<\/strong> is used to set or create variables depending on the value of source variables.<\/p>\n<p>For example:<\/p>\n<p>[js]<\/p>\n<p>map $http_user_agent $disallow {<br \/>\n\tdefault 0;<br \/>\n\t~*(curl|wget) 1;<br \/>\n}<\/p>\n<p>[\/js]<\/p>\n<p>In the code shown above, we have\u00a0created a variable named <strong>disallow <\/strong> whose value will depend upon the <strong>http_user_agent<\/strong> source variable. Now if the user agent is curl or wget, then <strong>disallow<\/strong> variable will take value 1 else it will remain\u00a00, which is the default value.<br \/>\n<a title=\"ngx_http_map_module\" href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_map_module.html\" target=\"_blank\">Reference: ngx_http_map_module<br \/>\n<\/a><\/p>\n<p>2. <strong>Geo module<\/strong> is used to set the value of variable depending on the value of client IP address.<\/p>\n<p>For example:<\/p>\n<p>[js]<\/p>\n<p>geo $myserver {<br \/>\n\tdefault 1;<br \/>\n\tx.x.x.x 0;<br \/>\n}<br \/>\n[\/js]<\/p>\n<p>Here, we have declared a variable <strong>myserver,<\/strong> whose value depends upon the IP address (x.x.x.x) mentioned in the block. If the value of \u00a0IP address is x.x.x.x then <strong>myserver<\/strong> value will be 0 else it will remain 1, which is the default value.<br \/>\n<a title=\"ngx_http_geo_module\" href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_geo_module.html\" target=\"_blank\">Reference: ngx_http_geo_module<\/a><\/p>\n<p>Now, based on the value of disallow and myserver variable, we will be able to reject requests coming from unknown IPs with a 403.<\/p>\n<p>We can define\u00a0these two modules in <strong>nginx.conf<\/strong> file under <strong>http block<\/strong> as shown below.<\/p>\n<p>[js]<\/p>\n<p>http {<\/p>\n<p>\tgeo $myserver{<br \/>\n\t\tdefault 1;<br \/>\n\t\tx.x.x.x 0;<br \/>\n\t\ty.y.y.y 0;<br \/>\n\t}<\/p>\n<p>\tmap $http_user_agent $disallow{<br \/>\n\t\tdefault 0;<br \/>\n\t\t~*(curl|wget) $myserver;<br \/>\n\t}<\/p>\n<p>}<\/p>\n<p>[\/js]<\/p>\n<p>The specific IPs (x.x.x.x and y.y.y.y) from which we want to allow wget and curl are defined in geo block of code. These IPs will set the value of the variable <strong>myserver<\/strong> to 0. Based on myserver value, the variable <strong>disallow<\/strong> in map block will be set. \u00a0In the example shown above, curl or wget user agents used by whitelisted IPs ( x.x.x.x\/y.y.y.y) will set the <strong>disallow<\/strong> variable value to 0.<\/p>\n<p>Now, the decision to accept or reject the curl\/wget request is based upon the value of disallow variable. This can be defined in the virtual host file of the nginx.<\/p>\n<p><strong>Sample Code<\/strong><\/p>\n<p>[js]<\/p>\n<p>server {<\/p>\n<p>\tlocation \/ {<\/p>\n<p>\t\tif($disallow) {<br \/>\n\t\t\treturn 403;<br \/>\n\t\t}<br \/>\n\t}<br \/>\n}<\/p>\n<p>[\/js]<\/p>\n<p>For whitelisted IPs, this code will be bypassed and for any other external users 403 error will be given as a result.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wget is a pretty handy tool that lets users download files from any HTTP\/HTTPS or FTP server. Curl, on the other hand is an amazing tool that helps you build a new request with plethora of protocols such as \u00a0HTTP, HTTPS, FTP, Telnet, SMTP etc. These tools can be used to test protocols or your [&hellip;]<\/p>\n","protected":false},"author":204,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":45},"categories":[1174,1],"tags":[814,2302,2307,2308,2305,2306,2303,2304,2301],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/25809"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/204"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=25809"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/25809\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=25809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=25809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=25809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}