diff --git a/ChangeLog b/ChangeLog
index a0c5991ba9ebc53ccdccd2ff2ee234b27fb20443..0df8124377a2273ef00cefd5c2706e16dacc17eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ Changes in version 0.0.9 - UNRELEASED:
  - Various meek_lite code cleanups and bug fixes.
  - Bug 29077: uTLS for ClientHello camouflage (meek_lite).
  - More fixes to HTTP Basic auth.
+ - (meek_lite) Pin the certificate chain public keys for the default
+   Tor Browser Azure bridge (meek_lite).
 
 Changes in version 0.0.8 - 2019-01-20:
  - Bug 24793: Send the correct authorization HTTP header for basic auth.
diff --git a/transports/meeklite/hpkp_lite.go b/transports/meeklite/hpkp_lite.go
new file mode 100644
index 0000000000000000000000000000000000000000..9e20d65e896e753a3b88d345e198080438c15ebe
--- /dev/null
+++ b/transports/meeklite/hpkp_lite.go
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019 Yawning Angel <yawning at schwanenlied dot me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package meeklite
+
+import (
+	"crypto/sha256"
+	"crypto/x509"
+	"encoding/base64"
+
+	"golang.org/x/net/idna"
+)
+
+var builtinPinDB *hpkpDatabase
+
+type hpkpDatabase struct {
+	pins map[string]map[string]bool
+}
+
+func (db *hpkpDatabase) HasPins(host string) (string, bool) {
+	h, err := normalizeHost(host)
+	return h, (db.pins[host] != nil && err == nil)
+}
+
+func (db *hpkpDatabase) Validate(host string, chains [][]*x509.Certificate) bool {
+	var ok bool
+	if host, ok = db.HasPins(host); !ok {
+		return false
+	}
+
+	pins := db.pins[host]
+	for _, chain := range chains {
+		for _, cert := range chain {
+			derivedPin := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
+			derivedPinEncoded := base64.StdEncoding.EncodeToString(derivedPin[:])
+			if !pins[derivedPinEncoded] {
+				return false
+			}
+		}
+	}
+
+	return true
+}
+
+func (db *hpkpDatabase) Add(host string, pins []string) {
+	h, err := normalizeHost(host)
+	if err != nil {
+		panic("failed to add hpkp pin, invalid host: " + err.Error())
+	}
+
+	pinMap := make(map[string]bool)
+	for _, pin := range pins {
+		pinMap[pin] = true
+	}
+
+	db.pins[h] = pinMap
+}
+
+func normalizeHost(host string) (string, error) {
+	return idna.Lookup.ToASCII(host)
+}
+
+func init() {
+	builtinPinDB = &hpkpDatabase{
+		pins: make(map[string]map[string]bool),
+	}
+
+	// Generated on 2019-02-04.
+	builtinPinDB.Add("ajax.aspnetcdn.com", []string{
+		"PPjoAKk+kCVr9VNPXJkyHXEKnIyd5t5NqpPL3zCvJOE=",
+		"wBdPad95AU7OgLRs0FU/E6ILO1MSCM84kJ9y0H+TT7s=",
+		"Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=",
+	})
+}
diff --git a/transports/meeklite/meek.go b/transports/meeklite/meek.go
index f86e9344bdd98819cbaa24c1a8b6bd32d66e602b..fc97d7f22df52b440dd77b212802e87b10161958 100644
--- a/transports/meeklite/meek.go
+++ b/transports/meeklite/meek.go
@@ -41,6 +41,7 @@ import (
 	gourl "net/url"
 	"os"
 	"runtime"
+	"strings"
 	"sync"
 	"time"
 
@@ -50,9 +51,10 @@ import (
 )
 
 const (
-	urlArg   = "url"
-	frontArg = "front"
-	utlsArg  = "utls"
+	urlArg         = "url"
+	frontArg       = "front"
+	utlsArg        = "utls"
+	disableHPKPArg = "disableHPKP"
 
 	maxChanBacklog = 16
 
@@ -76,7 +78,8 @@ type meekClientArgs struct {
 	url   *gourl.URL
 	front string
 
-	utls *utls.ClientHelloID
+	utls        *utls.ClientHelloID
+	disableHPKP bool
 }
 
 func (ca *meekClientArgs) Network() string {
@@ -114,6 +117,12 @@ func newClientArgs(args *pt.Args) (ca *meekClientArgs, err error) {
 		return nil, err
 	}
 
+	// Parse the (optional) HPKP disable argument.
+	hpkpOpt, _ := args.Get(disableHPKPArg)
+	if strings.ToLower(hpkpOpt) == "true" {
+		ca.disableHPKP = true
+	}
+
 	return ca, nil
 }
 
@@ -358,7 +367,7 @@ func newMeekConn(network, addr string, dialFn base.DialFunc, ca *meekClientArgs)
 	case nil:
 		rt = &http.Transport{Dial: dialFn}
 	default:
-		rt = newRoundTripper(dialFn, ca.utls)
+		rt = newRoundTripper(dialFn, ca.utls, ca.disableHPKP)
 	}
 
 	conn := &meekConn{
diff --git a/transports/meeklite/transport.go b/transports/meeklite/transport.go
index 2736fe10e3896d013f51c16c8a8aeb5bbc93dcc7..5817be0e7e87d45ef6d60790b6c619af3db26f4a 100644
--- a/transports/meeklite/transport.go
+++ b/transports/meeklite/transport.go
@@ -19,6 +19,7 @@ package meeklite
 
 import (
 	"crypto/tls"
+	"crypto/x509"
 	"errors"
 	"fmt"
 	"net"
@@ -28,6 +29,7 @@ import (
 	"strings"
 	"sync"
 
+	"gitlab.com/yawning/obfs4.git/common/log"
 	"gitlab.com/yawning/obfs4.git/transports/base"
 	utls "gitlab.com/yawning/utls.git"
 	"golang.org/x/net/http2"
@@ -64,7 +66,8 @@ type roundTripper struct {
 	dialFn        base.DialFunc
 	transport     http.RoundTripper
 
-	initConn net.Conn
+	initConn    net.Conn
+	disableHPKP bool
 }
 
 func (rt *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
@@ -128,7 +131,25 @@ func (rt *roundTripper) dialTLS(network, addr string) (net.Conn, error) {
 		host = addr
 	}
 
-	conn := utls.UClient(rawConn, &utls.Config{ServerName: host}, *rt.clientHelloID)
+	var verifyPeerCertificateFn func([][]byte, [][]*x509.Certificate) error
+	if !rt.disableHPKP {
+		if pinHost, ok := builtinPinDB.HasPins(host); ok {
+			if rt.transport == nil {
+				log.Debugf("meek_lite - HPKP enabled for host: %v", pinHost)
+			}
+			verifyPeerCertificateFn = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
+				if !builtinPinDB.Validate(pinHost, verifiedChains) {
+					log.Errorf("meek_lite - HPKP validation failure, potential MITM for host: %v", pinHost)
+					return fmt.Errorf("meek_lite: HPKP validation failure for host: %v", pinHost)
+				}
+				return nil
+			}
+		}
+	} else if rt.transport == nil {
+		log.Warnf("meek_lite - HPKP disabled for host: %v", host)
+	}
+
+	conn := utls.UClient(rawConn, &utls.Config{ServerName: host, VerifyPeerCertificate: verifyPeerCertificateFn}, *rt.clientHelloID)
 	if err = conn.Handshake(); err != nil {
 		conn.Close()
 		return nil, err
@@ -170,10 +191,11 @@ func getDialTLSAddr(u *url.URL) string {
 	return net.JoinHostPort(u.Host, strconv.Itoa(pInt))
 }
 
-func newRoundTripper(dialFn base.DialFunc, clientHelloID *utls.ClientHelloID) http.RoundTripper {
+func newRoundTripper(dialFn base.DialFunc, clientHelloID *utls.ClientHelloID, disableHPKP bool) http.RoundTripper {
 	return &roundTripper{
 		clientHelloID: clientHelloID,
 		dialFn:        dialFn,
+		disableHPKP:   disableHPKP,
 	}
 }