CVE-2017-7670
Description
The Traffic Router component of the incubating Apache Traffic Control project is vulnerable to a Slowloris style Denial of Service attack. TCP connections made on the configured DNS port will remain in the ESTABLISHED state until the client explicitly closes the connection or Traffic Router is restarted. If connections remain in the ESTABLISHED state indefinitely and accumulate in number to match the size of the thread pool dedicated to processing DNS requests, the thread pool becomes exhausted. Once the thread pool is exhausted, Traffic Router is unable to service any DNS request, regardless of transport protocol.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/apache/trafficcontrolGo | >= 1.1.4, < 1.8.1 | 1.8.1 |
github.com/apache/trafficcontrolGo | >= 2.0.0-RC0, < 2.0.0 | 2.0.0 |
github.com/apache/trafficcontrolGo | >= 2.1.0-RC0, < 2.1.0-RC1 | 2.1.0-RC1 |
github.com/apache/trafficcontrolGo | < 0.0.0-20170531185407-738c10fa1b58 | 0.0.0-20170531185407-738c10fa1b58 |
github.com/apache/trafficcontrolGo | >= 0.0.0, < 1.1.4-0.20170531185407-738c10fa1b58 | 1.1.4-0.20170531185407-738c10fa1b58 |
Affected products
9cpe:2.3:a:apache:traffic_control:*:*:*:*:*:*:*:*+ 7 more
- cpe:2.3:a:apache:traffic_control:*:*:*:*:*:*:*:*range: <=1.8.0
- cpe:2.3:a:apache:traffic_control:1.8.1:rc0:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc1:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc2:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc3:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc4:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc5:*:*:*:*:*:*
- cpe:2.3:a:apache:traffic_control:2.0.0:rc6:*:*:*:*:*:*
- Apache Software Foundation/Apache Traffic Controlv5Range: 1.8.0 incubating
Patches
1738c10fa1b58[TC-361] Added a read timeout to TCP DNS listener, and transaction timeout to both UDP and TCP. Also split thread pool so we have one per protocol.
4 files changed · +63 −11
traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/protocol/AbstractProtocol.java+25 −3 modified@@ -25,7 +25,11 @@ import org.xbill.DNS.WireParseException; import java.net.InetAddress; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public abstract class AbstractProtocol implements Protocol { private static final Logger ACCESS = Logger.getLogger("com.comcast.cdn.traffic_control.traffic_router.core.access"); @@ -34,6 +38,7 @@ public abstract class AbstractProtocol implements Protocol { protected boolean shutdownRequested; private ExecutorService executorService; private NameServer nameServer; + private int taskTimeout = 5000; // default /** * Gets executorService. @@ -138,9 +143,18 @@ protected byte[] query(final InetAddress client, final byte[] request) throws Wi * @param job * the handler to be executed */ - protected void submit(final Runnable job) { - executorService.submit(job); - } + protected void submit(final Runnable job) { + final Future<?> handler = executorService.submit(job); + executorService.submit(new Runnable() { + public void run() { + try { + handler.get(getTaskTimeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + handler.cancel(true); + } + } + }); + } private Message createServerFail(final Message query) { final Message response = new Message(); @@ -155,4 +169,12 @@ private Message createServerFail(final Message query) { response.getHeader().setRcode(Rcode.SERVFAIL); return response; } + + public int getTaskTimeout() { + return taskTimeout; + } + + public void setTaskTimeout(final int taskTimeout) { + this.taskTimeout = taskTimeout; + } }
traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/protocol/TCP.java+18 −3 modified@@ -18,16 +18,19 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.nio.channels.Channels; import org.apache.log4j.Logger; import org.xbill.DNS.Message; import org.xbill.DNS.WireParseException; public class TCP extends AbstractProtocol { private static final Logger LOGGER = Logger.getLogger(TCP.class); + private int readTimeout = 3000; // default private ServerSocket serverSocket; @@ -87,11 +90,12 @@ class TCPSocketHandler implements Runnable { @SuppressWarnings("PMD.EmptyCatchBlock") public void run() { try { + socket.setSoTimeout(getReadTimeout()); final InetAddress client = socket.getInetAddress(); - final DataInputStream is = new DataInputStream(socket.getInputStream()); + final InputStream iis = Channels.newInputStream(Channels.newChannel(socket.getInputStream())); + final DataInputStream is = new DataInputStream(iis); final DataOutputStream os = new DataOutputStream(socket.getOutputStream()); - final int length = is.readUnsignedShort(); final byte[] request = new byte[length]; is.readFully(request); @@ -121,5 +125,16 @@ public void shutdown() { } catch (IOException e) { LOGGER.warn("error on shutdown", e); } - } + } + + + public int getReadTimeout() { + return readTimeout; + } + + public void setReadTimeout(final int readTimeout) { + this.readTimeout = readTimeout; + } + + }
traffic_router/core/src/main/webapp/WEB-INF/applicationContext.xml+11 −3 modified@@ -242,7 +242,12 @@ <property name="trafficRouterManager" ref="trafficRouterManager" /> </bean> - <bean id="RequestHandlerExecutorService" class="java.util.concurrent.Executors" + <bean id="UDPRequestHandlerExecutorService" class="java.util.concurrent.Executors" + factory-method="newFixedThreadPool"> + <constructor-arg index="0" value="$[dns.max-threads:1000]" /> + </bean> + + <bean id="TCPRequestHandlerExecutorService" class="java.util.concurrent.Executors" factory-method="newFixedThreadPool"> <constructor-arg index="0" value="$[dns.max-threads:1000]" /> </bean> @@ -254,8 +259,10 @@ <bean id="TCP" class="com.comcast.cdn.traffic_control.traffic_router.core.dns.protocol.TCP"> <property name="serverSocket" ref="ServerSocket" /> - <property name="executorService" ref="RequestHandlerExecutorService" /> + <property name="executorService" ref="TCPRequestHandlerExecutorService" /> <property name="nameServer" ref="NameServer" /> + <property name="readTimeout" value="$[dns.tcp.timeout.read:3000]" /> + <property name="taskTimeout" value="$[dns.tcp.timeout.task:5000]" /> </bean> <bean id="DatagramSocket" class="java.net.DatagramSocket"> @@ -264,8 +271,9 @@ <bean id="UDP" class="com.comcast.cdn.traffic_control.traffic_router.core.dns.protocol.UDP"> <property name="datagramSocket" ref="DatagramSocket" /> - <property name="executorService" ref="RequestHandlerExecutorService" /> + <property name="executorService" ref="UDPRequestHandlerExecutorService" /> <property name="nameServer" ref="NameServer" /> + <property name="taskTimeout" value="$[dns.udp.timeout.task:5000]" /> </bean> <bean id="ProtocolExecutorService" class="java.util.concurrent.Executors"
traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/protocol/TCPTest.java+9 −2 modified@@ -19,7 +19,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; - import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -130,11 +129,12 @@ public void testTCPSocketHandlerBadMessage() throws Exception { final DataOutputStream dos = new DataOutputStream(baos); dos.writeShort(wireRequest.length); dos.write(wireRequest); + in = new ByteArrayInputStream(baos.toByteArray()); + when(socket.getInputStream()).thenReturn(in); final ByteArrayOutputStream out = new ByteArrayOutputStream(); when(socket.getOutputStream()).thenReturn(out); - handler.run(); assertThat(out.toByteArray().length, equalTo(0)); } @@ -147,6 +147,13 @@ public void testTCPSocketHandlerQueryFail() throws Exception { final Record question = Record.newRecord(name, Type.A, DClass.IN); final Message request = Message.newQuery(question); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final DataOutputStream dos = new DataOutputStream(baos); + dos.writeShort(request.toWire().length); + dos.write(request.toWire()); + in = new ByteArrayInputStream(baos.toByteArray()); + when(socket.getInputStream()).thenReturn(in); + final Message response = new Message(); response.setHeader(request.getHeader());
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-f2wr-c4c4-xjg7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-7670ghsaADVISORY
- github.com/apache/trafficcontrol/commit/738c10fa1b5861e4cc3944dc7c3065d16f4a708cghsaWEB
- github.com/apache/trafficcontrol/pull/633ghsaWEB
- github.com/apache/trafficcontrol/pull/634ghsaWEB
- lists.apache.org/thread.html/42b207e9f526353b504591684bd02a5e9fcb4b8f28534253d07740a0@%3Cusers.trafficcontrol.apache.org%3EghsaWEB
- lists.apache.org/thread.html/bb09fc29e9c2ee85b118a3d5748a8a523d30cf691ff8b606c6a1748c@%3Ccommits.trafficcontrol.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r3c675031ac220b5eae64a9c84a03ee60045c6045738607dca4a96cb8@%3Ccommits.trafficcontrol.apache.org%3EghsaWEB
- lists.apache.org/thread.html/42b207e9f526353b504591684bd02a5e9fcb4b8f28534253d07740a0%40%3Cusers.trafficcontrol.apache.org%3Envd
- lists.apache.org/thread.html/bb09fc29e9c2ee85b118a3d5748a8a523d30cf691ff8b606c6a1748c%40%3Ccommits.trafficcontrol.apache.org%3Envd
- lists.apache.org/thread.html/r3c675031ac220b5eae64a9c84a03ee60045c6045738607dca4a96cb8%40%3Ccommits.trafficcontrol.apache.org%3Envd
News mentions
0No linked articles in our index yet.