Question

For security purposes, I try to allow only Mandrill's IP(s) to access these urls.

Does anyone know them?

Was it helpful?

Solution 2

We have a range of IPs used for webhooks, but they can (and likely will) change or have new ones added as we scale. An alternative would be to add a query string to the webhook URL you add in Mandrill, and then check for that query string when a POST comes in so you can verify it's coming from Mandrill.

OTHER TIPS

Mandrill's signature is located in the HTTP response header: Authenticating-webhook-requests

In the request header find: X-Mandrill-Signature. This is a base64 of the hashcode, signed using web-hook key. This key is secret to your webhook only.

Just replace the constants and use this function:

<?php 

function generateSignature($post)
    {
        $signed_data = WEB_HOOK_URL;
        ksort($post);
        foreach ($post as $key => $value) {
            $signed_data .= $key;
            $signed_data .= $value;
        }

        return base64_encode(hash_hmac('sha1', $signed_data, WEB_HOOK_AUTH_KEY, true));
    }

//---

if (generateSignature($_POST) != $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) {
    //Invalid
}

?>

As described in mandrill's docs, they provide a signature to check if the request really came from them. to build the request there's a few steps:

  1. start with the exact url of your webhook (mind slashes and params)
  2. sort the post variables by key (in case of mandrill, you'll only have one post parameter: mandrill_events)
  3. add key and value to the url, without any delimiter
  4. hmac the url with your secret key (you can get the key from the web-interface) and base64 it.
  5. compare the result with the X-Mandrill-Signature header

here's a sample implementation in python:

import hmac, hashlib

def check_mailchimp_signature(params, url, key):
    signature = hmac.new(key, url, hashlib.sha1)
    for key in sorted(params):
        signature.update(key)
        signature.update(params[key])
    return signature.digest().encode("base64").rstrip("\n")

205.201.136.0/16

I have just whitelisted them in my server's firewall.

We don't need to white list the Ip they are using. Instead of that they have provided their own way to authenticate the webhook request.

When you are creating the mandrill webhook it will generate the key. It will come under the response we are getting to our post URL which is provided in the webhook.

public async Task<IHttpActionResult> MandrillEmailWebhookResponse()
        {
    string mandrillEvents = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", "");

                // validate the request is coming from mandrill API
                string url = ConfigurationManager.AppSettings["mandrillWebhookUrl"];
                string MandrillKey = ConfigurationManager.AppSettings["mandrillWebHookKey"];
                url += "mandrill_events";
                url += mandrillEvents;
                byte[] byteKey = System.Text.Encoding.ASCII.GetBytes(MandrillKey);
                byte[] byteValue = System.Text.Encoding.ASCII.GetBytes(url);

                HMACSHA1 myhmacsha1 = new HMACSHA1(byteKey);
                byte[] hashValue = myhmacsha1.ComputeHash(byteValue);
                string generatedSignature = Convert.ToBase64String(hashValue);

                string mandrillSignature = HttpContext.Current.Request.Headers["X-Mandrill-Signature"].ToString();

                if (generatedSignature == mandrillSignature)
                {
                    // validation = "Validation successful";
                    // do the updating using the response data
                }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top