Hi there,
Does CkoSshTunnel support ipv6?
My app was rejected due to the ipv6 support issue...
ChilkatLog: Connect_SshTunnel: DllDate: Sep 24 2017 ChilkatVersion: 9.5.0.70 Architecture: Little Endian; 64-bit Language: IOS C/C++/Swift/Objective-C VerboseLogging: 0 Component successfully unlocked using purchased unlock code. hostname: 165.227.202.20 port: 443 sshConnect: connectSocket: connect_ipv6_or_ipv4: socketErrno: 51 socketError: Network is unreachable --connect_ipv6_or_ipv4 connect_ipv6_or_ipv4: socketErrno: 51 socketError: Network is unreachable --connect_ipv6_or_ipv4 connect_ipv6_or_ipv4: socketErrno: 51 socketError: Network is unreachable --connect_ipv6_or_ipv4 connect_ipv6_or_ipv4: socketErrno: 51 socketError: Network is unreachable --connect_ipv6_or_ipv4 --connectSocket Failed to establish initial TCP/IP connection hostname: 165.227.202.20 port: 443 --sshConnect Failed. --Connect_SshTunnel --ChilkatLog
Thanks. I'll begin writing my answer here, and will be updating it because there is much to say. (This way you don't have to wait for the full answer..)
New Features in the 9.5.0.70 Pre-Release
The pre-release I provided to you has the following new features:
Did You Try Setting CkoSshTunnel.PreferIpv6 = YES?
Just in case you haven't, make sure you set either CkoGlobal.PreferIpv6 = YES, or sshTunnel.PreferIpv6 = YES.
You Can Take Matters Into Your Own Hands
In this case, you're writing code in Objective-C, which is just a superset of "C". Therefore, nothing stops you from calling getaddrinfo yourself to try to map your IPv4 address to an IPv6 address. If you can do that, then you can simply pass the IPv6 address string to CkoSshTunnel.Connect, and the problem should be solved.
Yes, of course, I set CkoSshTunnel.PreferIpv6 = YES
also, I wrote my custom resolver, but something wrong. Can you help me with it?
ChilkatLog:
Connect_SshTunnel:
DllDate: Sep 24 2017
ChilkatVersion: 9.5.0.70
Architecture: Little Endian; 64-bit
Language: IOS C/C++/Swift/Objective-C
VerboseLogging: 0
Component successfully unlocked using purchased unlock code.
hostname: 1c1e:1bb::2001:2:0:1baa
port: 443
sshConnect:
connectSocket:
connect_ipv6_or_ipv4:
timeout waiting for connect to complete;
failedWaitToConnect: Socket operation timeout.
--connect_ipv6_or_ipv4
--connectSocket
Failed to establish initial TCP/IP connection
hostname: 1c1e:1bb::2001:2:0:1baa
port: 443
--sshConnect
Failed.
--Connect_SshTunnel
--ChilkatLog
The above LastErrorText is for a call to CkoSshTunnel.Connect, which is to connect with an SSH server. Your port number, however, is 443. That makes no sense because port 443 is the customary port number for SSL/TLS for an HTTP server. Change 443 to 22, which is the customary port for SSH servers.
We configured the ssh port to 443. Ssh is the only service running on the server and it’s listening on port 443. But this port number works fine for ipv4... I don't think that port number is a cause of this problem.
Do you have some other suggestions?
ChilkatLog:
Connect_SshTunnel(30634ms):
DllDate: Sep 24 2017
ChilkatVersion: 9.5.0.70
UnlockPrefix: FEDCMS.CB10618
Architecture: Little Endian; 64-bit
Language: IOS C/C++/Swift/Objective-C
VerboseLogging: 1
Component successfully unlocked using purchased unlock code.
hostname: 1c1e:1bb::2001:2:0:1baa
port: 443
sshConnect(30634ms):
connectSocket(30634ms):
domainOrIpAddress: 1c1e:1bb::2001:2:0:1baa
port: 443
connectTimeoutMs: 30000
connect_ipv6_or_ipv4(30634ms):
This is an IPV6 numeric address.
Domain to IP address resolution not needed.
AddrInfoList:
AddrInfo:
ai_flags: 0
ai_family: 30
ai_socktype: 1
ai_protocol: 6
ai_addrlen: 28
ai_canonname: (NULL)
ipAddress: 1c1e:1bb::2001:2:0:1baa
--AddrInfo
--AddrInfoList
The application prefers IPv6 over IPv4. Looking for IPv6 addresses first...
connecting to IPV6 address...
ipAddress: 1c1e:1bb::2001:2:0:1baa
createSocket:
Setting SO_SNDBUF size
sendBufSize: 262144
Setting SO_RCVBUF size
recvBufSize: 4194304
--createSocket
connect(30634ms):
Waiting for the connect to complete...
timeout waiting for connect to complete;
failedWaitToConnect: Socket operation timeout.
--connect
--connect_ipv6_or_ipv4
--connectSocket
Failed to establish initial TCP/IP connection
hostname: 1c1e:1bb::2001:2:0:1baa
port: 443
--sshConnect
Failed.
--Connect_SshTunnel
--ChilkatLog
If the socket connection timed out, then either something is blocking the connection (such as a hardware or software firewall) or the IPv6 address is wrong.
Here's a new build with better logging:
https://chilkatdownload.com/prerelease/chilkat-9.5.0-ios9-259.zip
I would recommend doing something simple and experimenting. For example, create a CkoSocket object, and try connecting to various web servers using domain names, IPv4, and IPv6 addresses. Then see what can connect, and what does not.
Here are some samples. Connect to port 80 for all of them.
The information in the verbose LastErrorText should show you the exact values passed to getaddrinfo in each case. You can then compare those with what you are using in your custom resolver.
This new build: https://chilkatdownload.com/prerelease/chilkat-9.5.0-ios9-260.zip
Fixes an problem such that if PreferIpv6 is true, and your application is running on an IPv4-only network, then an IPv4 address will be used even if choices for both IPv6 and IPv4 are provided by getaddrinfo (internally).
I realize this wasn't the problem you're facing, but it's potentially another problem that you haven't encountered..
unfortunately, the library still fails on the apple NAT64 test network configuration using an ipv4 address, as well as an ipv6 address, but the ipv6 failure is probably due the the nat test configuration itself becuase ipv6 works fine on an ipv6 network.
Mentioned in point 3 under the "New Features in the 9.5.0.70 Pre-Release" post above that gettaddrinfo appears to be complicated, but it looks like apple lays everything out that needs to be done on this page: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html
see the sections "Check Source Code for IPv6 DNS64/NAT64 Incompatibilities" and "Use System APIs to Synthesize IPv6 Addresses"
So it looks like the solution may be that if you know you have an ipv4 address, you try to connect with it, and if it fails, execute the code that apple provides in this section: "Use System APIs to Synthesize IPv6 Addresses"
Thanks.
You mentioned this link: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html
At the aforementioned link, Apple provides a code snippet that supposedly can synthesize an IPv6 address from an IPv4 address:
Use System APIs to Synthesize IPv6 Addresses
If your app needs to connect to an IPv4-only server without a DNS hostname, use getaddrinfo to resolve the IPv4 address literal. If the current network interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64, performing this task will result in a synthesized IPv6 address.
Listing 10-1 shows how to resolve an IPv4 literal using getaddrinfo. Assuming you have an IPv4 address stored in memory as four bytes (such as {192, 0, 2, 1}), this example code converts it to a string (such as "192.0.2.1"), uses getaddrinfo to synthesize an IPv6 address (such as a struct sockaddr_in6 containing the IPv6 address "64:ff9b::192.0.2.1") and tries to connect to that IPv6 address.
Chilkat already does this exact thing. In fact, Chilkat was always doing it. The new versions I provided to you have two enhancements:
1) The exact inputs to getaddrinfo are logged in the LastErrorText. Specifically, Chilkat logs the hostname, the servname (which is a decimal port number), and the details passed in the hints. The hints.ai_flags are logged using the names, such as AI_ADDRCONFIG, AI_NUMERICSERV, etc. so that it's easy to see exactly which flags are set.
2) If the subsequent connect system function fails with the results from the getaddrinfo (or if the getaddrinfo did not return any sufficient results), then Chilkat re-tries with some alternative settings -- and you can see the retries w/ all the details in the LastErrorText.
I contend that what Apple claims about getaddrinfo being able to synthesize IPv6 addresses from an IPv4 address must not be working. (At least not in their environment when they are doing their testing -- but they provide you with no information, thank you very much Apple..)
It is entirely within your capability to play with the getaddrinfo code snippet provide by Apple at the above URL. See if you can synthesize an IPv6 address from an IPv4 address. If you can, then compare the values of the arguments you passed to getaddrinfo (including the hints) with what Chilkat logs in the LastErrorText. See if they are different, and let me know.
Of course, if you can synthesize the IPv6 address directly using getaddrinfo, then you can pass it to Chilkat instead of passing the IPv4 address.
I believe I've provided everything you need to move forward in solving this problem. If you find it impossible to synthesize an IPv6 address from an IPv4 address using getaddrinfo, then I don't know what else I can do. Also, if you can synthesize the IPv6 address in your test environment, and if Chilkat can also do it in your test environment, but Apple still rejects your app and provides no information to help you understand the reason, then I don't know what else I can do.
One possible way to avoid all of this trouble is to host your service on a computer/network such that it has both an IPv4 and IPv6 address. (i.e. an AAAA record) This way you can just avoid the entire IPv4-->IPv6 synthesis.