What type of asio resolver object should I use? - boost-asio

I am a little confused about which type of resolver I should use for a side project I am working on. I am not finding the answer in the asio documentation.
I know that DNS can work with both UDP or TCP and that larger responses are generally sent over TCP.
asio offers both ip::tcp::resolver and ip::udp::resolver.
Can I use them interchangeably?
After I have resolved the name to an endpoint, I plan to connect with
a TCP socket. Does that mean I have to use a ip::tcp::resolver?
If there are in fact interchangeable:
Is there a performance benefit to using the UDP resolver?
Is there a some other benefit to using the TCP resolver?
If I use UDP resolver, do I need to deal with the response being too large for the UDP lookup and retry with TCP? (I expect to connect to a CDN that will resolve to multiple IP addresses per host)

Use the resolver that has the same protocol as the socket. For example, tcp::socket::connect() expects a tcp::endpoint, and the endpoint type provided via udp::resolver::iterator is udp::endpoint. Attempting to directly use the result of the query from a different protocol will result in a compilation error:
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::udp::resolver::iterator iterator = ...;
socket.connect(iterator->endpoint());
// ~~~^~~~~~~ no matching function call to `tcp::socket::connect(udp::endpoint)`
// no known conversion from `udp::endpoint` to `tcp::endpoint`
Neither tcp::resolver nor udp::resolver dictate the transport layer protocol the name resolution will use. The DNS client will use TCP when either it become necessary or it has been explicitly configured to use TCP.
On systems where service name resolution is supported, when performing service-name resolution with a descriptive service name, the type of resolver can affect the results. For example, in the IANA Service Name and Transport Protocol Port Number Registry:
the daytime service uses port 13 on UDP and TCP
the shell service uses port 514 only on TCP
the syslog service uses port 514 only on UDP
Hence, one can use tcp::resolver to resolver the daytime and shell service, but not syslog. On the other hand, udp::resolver can resolve daytime and syslog, but not shell. The following example demonstrates this distinction:
#include <boost/asio.hpp>
int main()
{
boost::asio::io_service io_service;
using tcp = boost::asio::ip::tcp;
using udp = boost::asio::ip::udp;
boost::system::error_code error;
tcp::resolver tcp_resolver(io_service);
udp::resolver udp_resolver(io_service);
// daytime is 13/tcp and 13/udp
tcp_resolver.resolve(tcp::resolver::query("daytime"), error);
assert(!error);
udp_resolver.resolve(udp::resolver::query("daytime"), error);
assert(!error);
// shell is 514/tcp
tcp_resolver.resolve(tcp::resolver::query("shell"), error);
assert(!error);
udp_resolver.resolve(udp::resolver::query("shell"), error);
assert(error);
// syslog is 514/udp
tcp_resolver.resolve(tcp::resolver::query("syslog"), error);
assert(error);
udp_resolver.resolve(udp::resolver::query("syslog"), error);
assert(!error);
tcp_resolver.resolve(tcp::resolver::query("514"), error);
assert(!error);
udp_resolver.resolve(udp::resolver::query("514"), error);
assert(!error);
}

Related

Balancing export to jaeger in openTelemetry collector

I have configuration as documentation says
exporters:
jaeger:
endpoint: "ipv4:firstHost:14250,secondHost:14250"
balancer_name: "round_robin"
Collector produces error.
How I can configure collector to balance exporter for sending requests in different backends?
info exporterhelper/queued_retry.go:276 Exporting failed. Will retry the request after interval. {"component_kind": "exporter", "component_type": "jaeger", "component_name": "jaeger", "error": "failed to push trace data via Jaeger exporter: rpc error: code = Unavailable desc = last connection error: connection error: desc = "transport: Error while dialing dial tcp: address ipv4:firstHost:14250,secondHost:14250: too many colons in address"", "interval": "30.456378855s"}
It doesn't work in golang grpc client. I used openTelemetry load balancing Another option - use kubernetes to balance requests to backends.

RTCIceCandidate no longer returning IP

Just noticed that on Chrome only, RTCIceCandidate no longer returns an IP, but rather an obfuscated address.
RTCIceCandidate
address: "a5b3ef18-2e66-4e24-91d2-893b93bbc1c1.local"
candidate: "candidate:169888242 1 udp 2113937151 a5b3ef18-2e66-4e24-91d2-893b93bbc1c1.local 47871 typ host generation 0 ufrag 7dHv network-cost 999"
component: "rtp"
foundation: "169888242"
port: 47871
priority: 2113937151
protocol: "udp"
relatedAddress: null
relatedPort: null
sdpMLineIndex: 0
sdpMid: "0"
tcpType: ""
type: "host"
usernameFragment: "7dHv"
Notice the first property of RTCIceCanadate is "address", and "ip" is no longer part of this object.
The following code determines the local IP address of a browser. Still works on MOZ.
function discover()
{
try{
//Get Local IP
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
if (pc)
pc.close();
pc = new RTCPeerConnection({iceServers:[]});
pc.onicecandidate = onIceCandidate;
pc.createDataChannel("");
pc.createOffer(pc.setLocalDescription.bind(pc), noop);
} catch (e)
{ console.log(e.message);}
}
function noop()
{
}
function onIceCandidate(ice)
{
console.log(ice.candidate);
if(!ice || !ice.candidate || !ice.candidate.candidate) return;
var my_ip = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
this.onicecandidate = noop;
ip = my_ip.split(".")[0]+'.'+my_ip.split(".")[1]+'.'+my_ip.split(".")[2];
}
Is WebRTC officially now a fractured standard? MOZ still lists "ip" as a member of RTCIceCandidate, with no mention of the "address" member that Chrome returns.
Is there a way to de-obfusucate the mDNS address back to an ip address without forcing users to mess around with browser settings they don't understand?
Chrome is not broken, the WebRTC standard is evolving to prevent sites from collecting local addresses by diverting the WebRTC API. If you used this hack to obtain local addresses, you might need to find another approach.
Here are the corresponding issues for Chromium and Firefox, and the current IETF draft for WebRTC mDNS candidates.
The ip field got renamed to address in the W3C webrtc specification at some point since these days the field can contain either an IP address or a mdns hostname.
What you are seeing is part of the rollout of the WebRTC host candidate obfuscation which is described ħere which is happening in Chrome 75. You can not decode this mdns hostname in the browser.
If you have a legitimate use-case you might want to ask for it to be considered in that mailing list thread.
You can disable this feature in Chrome
goto chrome:://flags
and disable "Anonymize local IPs exposed by WebRTC"
I noticed that this was happening, only returning an mDNS address (for more information about the obfuscation, read this great article completely explaining what happened).
However, I did find a new repository that seems to "fix" this (working, but not exposing the private ip, only the public). It can be found here, and the example can be found here.

How to handle SSL handshake failure in Netty

We're implementing SSL on top of Netty. But there's a flaw in current design. The client will retry connecting to server if failed. This is desired in Network or heavy server load issues. But wrong client credentials would cause constant failure.
There're some solutions:
The client-server connection can failover to unencrypted mode
(removing SslHandler from pipeline).
Client can die and throw exception on knowing it's SSL exception.
Unfortunately I don't know how to implement this using Netty. A few questions:
How to detect it's SSL exception?
How to remove the SslHandler from both side safely?
Please help out here.
As far as I know, there's no safe way to downgrade an SSL connection to a plaintext connection.
To detect a handshake failure, you need to implement userEventTriggered() handler method:
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SslHandshakeCompletionEvent) {
if (!((SslHandshakeCompletionEvent) evt).isSuccess()) {
// handshake failed
}
}
}
You can also add a listener to the handshake future:
ChannelPipeline p = ...;
SslHandler sslHandler = p.get(SslHandler.class);
sslHandler.handshakeFuture().addListener(new FutureListener<Channel> { ... });

ActiveMQ embedded broker force to listen to ip instead of hostname

We use an embedded ActiveMQ broker and create it like this(a bit simplified) :
BrokerService brokerService = new BrokerService();
brokerService.addConnector("tcp://1.2.3.4:61610");
brokerService.start();
The problem we have is that the broker is listening to the hostname instead of the IP-address and this does not work in our case. How can I force the brokerService to listen on the IP address instead of the hostname.
Here is what the log says when starting the broker:
2015-01-20 15:16:03,414 qtp833534789-27 INFO BrokerService - Apache ActiveMQ 5.10.0 (b1653842572, ID:ABC123-59162-1421763362756-0:1) is starting
2015-01-20 15:16:04,948 qtp833534789-27 INFO TransportServerThreadSupport - Listening for connections at: tcp://myhostname.mydomain.local:61610
2015-01-20 15:16:04,948 qtp833534789-27 INFO TransportConnector - Connector tcp://myhostname.mydomain.local:61610 started
A TCP listener can never listen to a DNS name. It's always bound to one or many interface(s)/IP address(es).
In this case, ActiveMQ helps you out by reverse resolving the DNS name from the IP because it's easier to understand what's going on in the logs when you read a logical DNS name rather than some number.
ActiveMQ has some code like this
protected String resolveHostName(ServerSocket socket, InetAddress bindAddress) throws UnknownHostException {
String result = null;
if (socket.isBound()) {
if (socket.getInetAddress().isAnyLocalAddress()) {
// make it more human readable and useful, an alternative to 0.0.0.0
result = InetAddressUtil.getLocalHostName();
} else {
result = socket.getInetAddress().getCanonicalHostName();
}
} else {
result = bindAddress.getCanonicalHostName();
}
return result;
}
To replace the IP with a DNS once the socket is indeed bound. I guess you have not even tried using the IP address, since it should work.
Try this:
brokerService.addConnector("tcp://0.0.0.0:61610");

How to set keepalive option for induvidual socket in VxWorks

Is there any way to set keepalive for induvidual socket descriptor in vxworks? I read in some documents that "SOL_TCP" option in setsockopt function will do such favors in linux. Is such facility available in VxWorks too? If so please provide related details regarding the same, like what are the include file we need to include and how to use such option etc.
From the VxWorks "Library Reference" manual (can be download):
OPTIONS FOR STREAM SOCKETS
The following sections discuss the socket options available for stream (TCP) sockets.
SO_KEEPALIVE -- Detecting a Dead Connection
Specify the SO_KEEPALIVE option to make the transport protocol (TCP) initiate a timer to detect a dead connection:
setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval));
This prevents an application from hanging on an invalid connection. The value at optval for this option is an integer (type int), either 1 (on) or 0 (off).
The integrity of a connection is verified by transmitting zero-length TCP segments triggered by a timer, to force a response from a peer node. If the peer does not respond after repeated transmissions of the KEEPALIVE segments, the connection is dropped, all protocol data structures are reclaimed, and processes sleeping on the connection are awakened with an ETIMEDOUT error.
The ETIMEDOUT timeout can happen in two ways. If the connection is not yet established, the KEEPALIVE timer expires after idling for TCPTV_KEEP_INIT. If the connection is established, the KEEPALIVE timer starts up when there is no traffic for TCPTV_KEEP_IDLE. If no response is received from the peer after sending the KEEPALIVE segment TCPTV_KEEPCNT times with interval TCPTV_KEEPINTVL, TCP assumes that the connection is invalid. The parameters TCPTV_KEEP_INIT, TCPTV_KEEP_IDLE, TCPTV_KEEPCNT, and TCPTV_KEEPINTVL are defined in the file target/h/net/tcp_timer.h.
IP_TCP_KEEPINTVL and also TCP_KEEPIDLE, TCP_KEEPCNT options supported by setsockopt after vxworks 6.8 version. In former releases of vxworks you can change these values globally and all the sockets created effected.
Below question is an answer for how will it be done.
How to set TCP keep alive interval for a specific socket fd (Not system wide) in VxWorks?