diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index 4ddd9255..bd103d9f 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -375,6 +375,8 @@ static const struct argp_option options[] =
 #define ARGP_KEY_FDCACHE_PREFETCH_FDS 0x1006
    { "fdcache-prefetch-fds", ARGP_KEY_FDCACHE_PREFETCH_FDS, "NUM",
0,"Number of files allocated to the \
       prefetch cache.", 0},
+#define ARGP_KEY_FORWARDED_TTL_LIMIT 0x1007
+   {"forwarded-ttl-limit", ARGP_KEY_FORWARDED_TTL_LIMIT, "NUM", 0, "Limit
of X-Forwarded-For hops, default 8.", 0},
    { NULL, 0, NULL, 0, NULL, 0 },
   };

@@ -422,6 +424,7 @@ static long fdcache_prefetch;
 static long fdcache_mintmp;
 static long fdcache_prefetch_mbs;
 static long fdcache_prefetch_fds;
+static unsigned forwarded_ttl_limit = 8;
 static string tmpdir;

 static void set_metric(const string& key, double value);
@@ -554,6 +557,9 @@ parse_opt (int key, char *arg,
       if( fdcache_mintmp > 100 || fdcache_mintmp < 0 )
         argp_failure(state, 1, EINVAL, "fdcache mintmp percent");
       break;
+    case ARGP_KEY_FORWARDED_TTL_LIMIT:
+      forwarded_ttl_limit = (unsigned) atoi(arg);
+      break;
     case ARGP_KEY_ARG:
       source_paths.insert(string(arg));
       break;
@@ -1769,7 +1775,8 @@ handle_buildid (MHD_Connection* conn,
                 const string& buildid /* unsafe */,
                 const string& artifacttype /* unsafe */,
                 const string& suffix /* unsafe */,
-                int *result_fd)
+                int *result_fd,
+                bool disable_query_server = false)
 {
   // validate artifacttype
   string atype_code;
@@ -1862,6 +1869,12 @@ handle_buildid (MHD_Connection* conn,
   // We couldn't find it in the database.  Last ditch effort
   // is to defer to other debuginfo servers.

+  // if X-Forwarded-For: exceeds N hops,
+  // do not delegate a local lookup miss to upstream debuginfods.
+  if (disable_query_server)
+    throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found,
--forwared-ttl-limit reached \
+and will not query the upstream servers");
+
   int fd = -1;
   debuginfod_client *client = debuginfod_pool_begin ();
   if (client != NULL)
@@ -2119,6 +2132,7 @@ handler_cb (void * /*cls*/,
   struct timespec ts_start, ts_end;
   clock_gettime (CLOCK_MONOTONIC, &ts_start);
   double afteryou = 0.0;
+  bool disable_query_server = false;

   try
     {
@@ -2131,6 +2145,17 @@ handler_cb (void * /*cls*/,

       if (slash1 != string::npos && url1 == "/buildid")
         {
+          // check if X-Forwarded-For exceeds the limit number of hops.
+          string xff = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND, "X-Forwarded-For") ?: "";
+
+          unsigned int xff_count = 0;
+          for (auto&& i : xff){
+            if (i == ',') xff_count++;
+          }
+
+          if (xff_count >= forwarded_ttl_limit)
+            disable_query_server = true;
+
           // PR27863: block this thread awhile if another thread is
already busy
           // fetching the exact same thing.  This is better for Everyone.
           // The latecomer says "... after you!" and waits.
@@ -2171,7 +2196,7 @@ handler_cb (void * /*cls*/,

           // get the resulting fd so we can report its size
           int fd;
-          r = handle_buildid(connection, buildid, artifacttype, suffix,
&fd);
+          r = handle_buildid(connection, buildid, artifacttype, suffix,
&fd, disable_query_server);
           if (r)
             {
               struct stat fs;
@@ -3719,6 +3744,7 @@ main (int argc, char *argv[])
   obatched(clog) << "groom time " << groom_s << endl;
   obatched(clog) << "prefetch fds " << fdcache_prefetch_fds << endl;
   obatched(clog) << "prefetch mbs " << fdcache_prefetch_mbs << endl;
+  obatched(clog) << "forwarded ttl limit " << forwarded_ttl_limit << endl;

   if (scan_archives.size()>0)
     {
diff --git a/doc/debuginfod.8 b/doc/debuginfod.8
index f70af625..4f532cb8 100644
--- a/doc/debuginfod.8
+++ b/doc/debuginfod.8
@@ -236,6 +236,12 @@ are intended to give an operator notice about storage
scarcity - which
 can translate to RAM scarcity if the disk happens to be on a RAM
 virtual disk.  The default threshold is 25%.

+.TP
+.B "\-\-forwarded\-ttl\-limit=NUM"
+Configure limits of X-Forwarded-For hops. if X-Forwarded-For
+exceeds N hops, it will not delegate a local lookup miss to
+upstream debuginfods. The default limit is 8.
+
 .TP
 .B "\-v"
 Increase verbosity of logging to the standard error file descriptor.
diff --git a/tests/run-debuginfod-find.sh b/tests/run-debuginfod-find.sh
index 991d1dc5..dbf20975 100755
--- a/tests/run-debuginfod-find.sh
+++ b/tests/run-debuginfod-find.sh
@@ -37,6 +37,8 @@ PID1=0
 PID2=0
 PID3=0
 PID4=0
+PID5=0
+PID6=0

 cleanup()
 {
@@ -44,6 +46,8 @@ cleanup()
   if [ $PID2 -ne 0 ]; then kill $PID2; wait $PID2; fi
   if [ $PID3 -ne 0 ]; then kill $PID3; wait $PID3; fi
   if [ $PID4 -ne 0 ]; then kill $PID4; wait $PID4; fi
+  if [ $PID5 -ne 0 ]; then kill $PID5; wait $PID5; fi
+  if [ $PID6 -ne 0 ]; then kill $PID6; wait $PID6; fi
   rm -rf F R D L Z ${PWD}/foobar ${PWD}/mocktree ${PWD}/.client_cache*
${PWD}/tmp*
   exit_cleanup
