Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to connect to redis that listening on IPv6 interface #512

Closed
morawskim opened this issue Jan 28, 2023 · 5 comments
Closed

Unable to connect to redis that listening on IPv6 interface #512

morawskim opened this issue Jan 28, 2023 · 5 comments

Comments

@morawskim
Copy link

morawskim commented Jan 28, 2023

Hello,

The redis-commander has problem with connecting to redis that listening on IPv6 interface.

I deployed rediscommander using image rediscommander/redis-commander:latest (docker.io/rediscommander/redis-commander@sha256:19cd0c49f418779fa2822a0496c5e6516d0c792effc39ed20089e6268477e40a ). When I tried to connect to configured redis server (added by env variable) in logs I noticed errors:

MaxRetriesPerRequestError: Reached the max retries per request limit (which is 20). Refer to "maxRetriesPerRequest" option for details.                                           
    at Socket.<anonymous> (/redis-commander/node_modules/ioredis/built/redis/event_handler.js:176:37)                                                                   
    at Object.onceWrapper (events.js:421:26)
    at Socket.emit (events.js:314:20)
    at TCP.<anonymous> (net.js:675:12)
setUpConnection (R:redis:6379:0) Redis error Error: getaddrinfo ENOTFOUND redis                                                                                                                            
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26)

I changed my deployment manifest. I added:

#...
      securityContext:
        runAsUser: 0

After this change I was able to exec to running pod with root privileges.
I installed redis.
Using redis-cli -h redis I was able to connect to redis instance and call ping command.

I checked source code and i found this -

family: 4

Object.assign(redisOpts, {
    port: clientConfig.port,
    host: clientConfig.host,
    path: clientConfig.path,
    family: 4
});

I changed the value of family property to 6.
I ran ps -ef to see running commands.
I decided to ran a new instane of redis-commander on a different port: /usr/bin/node ./bin/redis-commander --port 8082 --redis-port tcp://[fd2e:565e:ab48::XXXX]:6379.
I used kubectl port-forward to connect to a new redis-commander instance and everything worked - I connected to redis and I saw all my keys in db.

At the moment neither minikube (https://minikube.sigs.k8s.io/docs/faq/#does-minikube-support-ipv6) nor microk8s (canonical/microk8s#1343) support IPv6 stack. So I cannot prepare example.
I have access to k8s cluster which run on ipv6 stack, so I am able to test fix.

@sseide
Copy link
Collaborator

sseide commented Jan 31, 2023

Hi, thanks for the report.

As a short recap from your tests/doings:

  • in principal it is possible to connect to Redis with IPv6
  • changing the family for ioredis connection properties is neccessary
  • additionally docker runtime / kubernetes cluster must be reconfigured to use IPv6 (i know its not possible out-of-the-box)

After theses steps its working...

Base on this i can prepare a Change and push it this week. Please correct me if i'm wrong or missed something as i do not know if i can setup an test environment locally right now.

And another note - since some time its not possible to update the dockerhub image anymore. Latest versions are available from gcr.io - please check projects README here for up to date image repo.

Best regards,
S. Seide

@morawskim
Copy link
Author

Yeap everything correct. I am waiting for patch to test it.

I will use image from gcr.io registry, thanks for info.

I also thought about create a test env in virtualbox, but there are some issues also with VB and IPv6 :/
I had to manually add a NAT network for VB on Linux (vagrant was not able to create IPv6 network/assign IPv6 address) - this thread can be useful https://askubuntu.com/questions/803102/virtualbox-no-ipv6-in-ubuntu-guest-win10-host (the steps are the same also for linux)

sseide added a commit to sseide/redis-commander that referenced this issue Feb 2, 2023
@sseide
Copy link
Collaborator

sseide commented Feb 3, 2023

latest Version from gcr.io should work. Can you please test it? Runing locally it can connect to IPv6 server.

Using Docker you may set the env var REDIS_HOST=fd2e:565e:ab48::XXXX (no bracket). REDIS_PORT is not needed as long as it is the default 6379.

Booth REDIS_HOSTS and SENTINEL_HOSTS (plural) to set multiple connections at once do not work with IPv6 addresses currently. Do you know a simple way in Shell/Bash to split IPv6 addresses and ports?

And thanks for VB/Vagrant info - used it to update my redis test vm for ipv6 connectivity.

@morawskim
Copy link
Author

Hello,

I have tested the latest version. Everything works. Thanks.

Do you know a simple way in Shell/Bash to split IPv6 addresses and ports?

This doesn't look like a trivial task. The ENTRYPOINT script accept entry in REDIS_HOSTS as label:hostname:port:dbIndex:password
I created test script. The only idea I have, is to wrap a IPv6 address into square brackets.

First we can check whether hostname looks like ipv4, then check first character (whether is equals to [) and then assume that this is hostname.
But still there can be issue with current template in REDIST_HOSTS, because contains information not only about hostname and port, but also about dbindex and password.

#!/bin/bash -e

IP_ADDRESSES=(
    '2001:0db8:85a3:0000:0000:8a2e:0370:7334:PORTHERE'
    '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
    '127.0.0.1:PORTHERE'
    '127.0.0.1'
    '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:PORTHERE'
    '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]'
    'dnsname'
    'dnsname:PORTHERE'
)

for ip in ${IP_ADDRESSES[@]}; do
  printf ">>> %52s" $ip
  echo

  if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ ]]; then
    chunks=($(echo $ip | sed 's|\(.*\):|\1 |'))
  elif [[ $ip =~ ^\[ ]]; then
    chunks=($(echo $ip | sed 's|\(.*\)]:|\1] |'))
  else
    chunks=($(echo $ip | sed 's|\(.*\):|\1 |'))
  fi

  printf "IP: %52s   PORT: %4s" ${chunks[0]:-''} ${chunks[1]:-6379}
  echo
  echo
done

Which gives results

>>>     2001:0db8:85a3:0000:0000:8a2e:0370:7334:PORTHERE
IP:              2001:0db8:85a3:0000:0000:8a2e:0370:7334   PORT: PORTHERE

>>>              2001:0db8:85a3:0000:0000:8a2e:0370:7334
IP:                   2001:0db8:85a3:0000:0000:8a2e:0370   PORT: 7334

>>>                                   127.0.0.1:PORTHERE
IP:                                            127.0.0.1   PORT: PORTHERE

>>>                                            127.0.0.1
IP:                                            127.0.0.1   PORT: 6379

>>>   [2001:0db8:85a3:0000:0000:8a2e:0370:7334]:PORTHERE
IP:            [2001:0db8:85a3:0000:0000:8a2e:0370:7334]   PORT: PORTHERE

>>>            [2001:0db8:85a3:0000:0000:8a2e:0370:7334]
IP:            [2001:0db8:85a3:0000:0000:8a2e:0370:7334]   PORT: 6379

>>>                                              dnsname
IP:                                              dnsname   PORT: 6379

>>>                                     dnsname:PORTHERE
IP:                                              dnsname   PORT: PORTHERE

@sseide
Copy link
Collaborator

sseide commented Feb 6, 2023

Many thanks for this. And having multiple fields like label and so on i say using square brackets for ipv6 addresses will be required for these envs vars. Makes parsing a lot easier than. Port and/or db number might be given and using the shortened ipv6 writing with "fd00::1" it is indistinguishable...

Writing "fd00::1:1024:1" means what?

  • ipv6 "fd00::1:2048:1" with default port 6379 and default db 0 or
  • ipv6 "fd00::1" with port 2048 and db 1
  • and so on...

And maybe i parse these in nodejs, a little helper script called from the docker-startup like other regular programs might be easier than a pure shell script...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants