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

xrdp - vnc connection does not work in pure IPv4 scenario #1596

Closed
tiago-as opened this issue Jun 2, 2020 · 13 comments · Fixed by #2207
Closed

xrdp - vnc connection does not work in pure IPv4 scenario #1596

tiago-as opened this issue Jun 2, 2020 · 13 comments · Fixed by #2207

Comments

@tiago-as
Copy link

tiago-as commented Jun 2, 2020

Hi, I have configured xrdp to communicate with a x11vnc server in localhost. I noticed that in some machines that I managed this didn't work. I noticed through tcpdump that xrdp was trying to communicate with vnc using IPv6. The machines where this didn't work have IPv6 disabled through firewall rules.
xrdp.ini:

[globals]
ini_version=1
bitmap_cache=yes
bitmap_compression=yes
port=3389
crypt_level=low
channel_code=1
max_bpp=24
ssl_protocols=TLSv1.2, TLSv1.3
allow_channels=true
[Logging]
LogFile=xrdp.log
LogLevel=DEBUG
EnableSyslog=true
SyslogLevel=DEBUG
[Channels]
; Channel names not listed here will be blocked by XRDP.
; You can block any channel by setting its value to false.
; IMPORTANT! All channels are not supported in all use
; cases even if you set all values to true.
; You can override these settings on each session type
; These settings are only used if allow_channels=true
rdpdr=true
rdpsnd=true
drdynvc=true
cliprdr=true
rail=true
xrdpvr=true
tcutils=true
[Console]
name=console
lib=libvnc.so
ip=127.0.0.1
port=5900
password=ask

Command used to launch x11vnc:

x11vnc -listen 127.0.0.1 -no6 -rfbportv6 -1 -accept popup

From my understanding, with these configurations there should be no reason for xrdp to be using IPv6, and still I see this on tcpdump:

18:52:58.852891 IP6 ip6-localhost.51474 > ip6-localhost.5900: Flags [S], seq 2933527359, win 65476, options [mss 65476,sackOK,TS val 2368947658 ecr 0,nop,wscale 7], length 0
18:52:58.852925 IP6 ip6-localhost.5900 > ip6-localhost.51474: Flags [R.], seq 0, ack 2933527360, win 0, length 0
18:52:58.953630 IP localhost.54790 > localhost.5900: Flags [S], seq 2933527362, win 65495, options [mss 65495,sackOK,TS val 1807070734 ecr 0,nop,wscale 7], length 0
18:52:58.953663 IP localhost.5900 > localhost.54790: Flags [S.], seq 143156007, ack 2933527363, win 65483, options [mss 65495,sackOK,TS val 1807070734 ecr 1807070734,nop,wscale 7], length 0
18:52:58.953695 IP localhost.54790 > localhost.5900: Flags [.], ack 1, win 512, options [nop,nop,TS val 1807070734 ecr 1807070734], length 0
18:52:59.083123 IP localhost.5900 > localhost.54790: Flags [P.], seq 1:13, ack 1, win 512, options [nop,nop,TS val 1807070863 ecr 1807070734], length 12
18:52:59.083165 IP localhost.54790 > localhost.5900: Flags [.], ack 13, win 512, options [nop,nop,TS val 1807070863 ecr 1807070863], length 0
18:52:59.083580 IP localhost.54790 > localhost.5900: Flags [P.], seq 1:13, ack 13, win 512, options [nop,nop,TS val 1807070864 ecr 1807070863], length 12
18:52:59.083754 IP localhost.5900 > localhost.54790: Flags [.], ack 13, win 512, options [nop,nop,TS val 1807070864 ecr 1807070864], length 0

I would like to have xrdp communicate purely through IPv4 with vnc. Is there a way to do this? I haven't find any options to control this.

Thanks in advance

@metalefty
Copy link
Member

AFAIK there's no way to do that right now however it is the issue to be addressed.

@metalefty
Copy link
Member

Hmm, as far as my reading of code, connect_loopback() tries IPv6 first and then IPv4.
https://github.com/neutrinolabs/xrdp/blob/v0.9.13/common/os_calls.c#L769-L821

So even only IPv4 is available, it will fall back to IPv4 finally. I believe VNC connection will finally success with IPv4.

@tiago-as
Copy link
Author

tiago-as commented Jun 3, 2020

Hi @metalefty thanks for the quick response. I understand that it falls back to IPv4, but that only happens if the firewall lets the IPv6 packages go through. In my test with those machines I opened the firewall so it accepted the IPv4 communication on the loop back interface but xrdp never started the IPv4 connection, it just fails after the sending IPv6 packages.

@tiago-as
Copy link
Author

tiago-as commented Jun 3, 2020

@metalefty just to be clear: the firewall on those machines DROPs the ipv6 traffic and the connection attempt somehow does not make it to the ipv4 section of the code; when the firewall is off and there is nothing listening as ipv6 xrdp ends up connecting to ipv4; but unfortunately on these machines it is mandatory to have the firewall on.

A suggestion would be having a configuration variable that control the IP version used to connect to vnc: 4, 6 or both

@matt335672
Copy link
Member

This particular issue is almost certainly happening as the firewall DROP is causing the IPV6 connect attempt to return INPROGRESS, so IPV4 is never tried.

There's a bit of a problem here - if a connect() fails, the socket is left in an indeterminate state, and so it's not clear whether a subsequent connect() on the same descriptor will be allowed or not.

I've had a read of #714 too which is the last time this area of code was touched. Any changes will need quite a bit of testing, so this particular problem is going to need more effort to solve than is obvious at first sight.

@matt335672
Copy link
Member

I can't see any workarounds to the immediate problem. The simplest solution I can see currently is to recompile xrdp without --enable-ipv6. Are you in a position to do that, @tiago-as ?

@tiago-as
Copy link
Author

tiago-as commented Jun 5, 2020

@matt335672 thanks so much for the answer.
At the moment we found away of making it work by opening just the needed port or the ipv6 connection. So for this specific matter we are fine at the moment and we don't need to rebuild the package. I appreciate you guys taking the time to make sure this works, once it works in a pure IPv4 environment we will then completely drop the IPv6 traffic.

I'll leave here the firewall rules that we are using in case somebody else needs them:

$ sudo ip6tables-save 
# Generated by ip6tables-save v1.8.4 on Fri Jun  5 15:17:58 2020
*filter
:INPUT DROP [36:3211]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [17:1526]
-A INPUT -p tcp -m multiport --sports 5900 -m state --state ESTABLISHED -j ACCEPT
-A INPUT -i lo -p tcp -m multiport --dports 5900 -j ACCEPT
COMMIT
# Completed on Fri Jun  5 15:17:58 2020

Thank you once again.

@jblaine
Copy link

jblaine commented Feb 19, 2021

This Ubuntu host has the firewall turned off and flushed and still cannot start xrdp-sesman on the host because we have IPv6 disabled.

● xrdp-sesman.service - xrdp session manager
   Loaded: loaded (/lib/systemd/system/xrdp-sesman.service; disabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Fri 2021-02-19 16:31:58 EST; 1min 2s ago
     Docs: man:xrdp-sesman(8)
           man:sesman.ini(5)
  Process: 25092 ExecStart=/usr/sbin/xrdp-sesman $SESMAN_OPTIONS (code=exited, status=1/FAILURE)

Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25105]: (25105)(140548252538176)[INFO ] IPv6 not supported, falling back to IPv4
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25092]: (25092)(140548252538176)[DEBUG] Testing if xrdp-sesman can listen on 127.0.0.1 port 3350.
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25105]: (25105)(140548252538176)[INFO ] listening to port 3350 on 127.0.0.1
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25092]: (25092)(140548252538176)[ERROR] bind_loopback(5, 3350) failed; IPv6 ::1 (errno=97), IPv4 127.0.0.1 (errno=98) and IPv6 ::FFFF:127.0.0.1 (errno=97).
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25092]: (25092)(140548252538176)[ERROR] Failed to start xrdp-sesman daemon, possibly address already in use.
Feb 19 16:31:58 ipac-ub18-tplt systemd[1]: xrdp-sesman.service: Control process exited, code=exited status=1
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25105]: (25105)(140548252538176)[INFO ] shutting down sesman 1
Feb 19 16:31:58 ipac-ub18-tplt xrdp-sesman[25105]: (25105)(140548252538176)[DEBUG] Closed socket 7 (AF_INET 127.0.0.1:3350)
Feb 19 16:31:58 ipac-ub18-tplt systemd[1]: xrdp-sesman.service: Failed with result 'exit-code'.
Feb 19 16:31:58 ipac-ub18-tplt systemd[1]: Failed to start xrdp session manager.

@matt335672
Copy link
Member

We're looking at moving this interface to a UNIX domain socket which will make this problem go away.

Can you try using "127.0.0.2" as a workaround in /etc/xrdp/sesman.ini?

@jblaine
Copy link

jblaine commented Feb 22, 2021

Hi. Using 127.0.0.2 bought me nothing and shows a different error:

Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66255]: (66255)(140591463961920)[INFO ] IPv6 not supported, falling back to IPv4
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66254]: (66254)(140591463961920)[DEBUG] Testing if xrdp-sesman can listen on 127.0.0.2 port 3350.
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66255]: (66255)(140591463961920)[INFO ] listening to port 3350 on 127.0.0.2
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66254]: (66254)(140591463961920)[ERROR] g_tcp_bind_address(5, 3350, 127.0.0.2) Failed!
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66254]: (66254)(140591463961920)[ERROR] Failed to start xrdp-sesman daemon, possibly address already in use.
Feb 22 11:31:35 ipac-ub18-tplt systemd[1]: xrdp-sesman.service: Control process exited, code=exited status=1
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66255]: (66255)(140591463961920)[INFO ] shutting down sesman 1
Feb 22 11:31:35 ipac-ub18-tplt xrdp-sesman[66255]: (66255)(140591463961920)[DEBUG] Closed socket 7 (AF_INET 127.0.0.2:3350)
Feb 22 11:31:35 ipac-ub18-tplt systemd[1]: xrdp-sesman.service: Failed with result 'exit-code'.
Feb 22 11:31:35 ipac-ub18-tplt systemd[1]: Failed to start xrdp session manager.

@matt335672
Copy link
Member

Interesting.

I've done a lot of work on this, and the fundamental problem seems to be that sesman is creating a socket with this call:-

socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 3

and then any attempt to bind pure IPv4 to it will necessarily fail.

There's no way round this at the moment, short of recompiling xrdp without --enable-ipv6. Are you in a position to do this?

@jblaine
Copy link

jblaine commented Feb 26, 2021

Thanks, Matt. I see it now. g_tcp_bind_address is failing because the code is not written to fully adapt to the lack of IPV6 at runtime and is wrongly choosing the IPV6 #ifdef'd version of that function after noticing that IPv6 isn't supported. Need some sort of runtime-set "ipv6 enabled but not supported in OS" flag or something I guess.

If you need me to compile in order to confirm that leaving out --enable-ipv6 solves the issue, I can try. But no, we're not going down the path of our own package building for addressing our host/user needs.

@matt335672
Copy link
Member

Yes, that's my appraisal of the situation too.

I think the correct fix here is to move to a UNIX domain socket for this interface. It removes the whole IPv4/IPv6 issue from this connection. It still needs addressing of course to fully support things like NeutrinoRDP, but not everyone is using that, whereas pretty much everyone is using the sesman connection.

Thanks for the compilation offer, but I think we're clear about the actual issue now. Other than the recompile I can't offer you a non-hacky solution I'm afraid. Even if I did have a magic code patch to hand, it's not going to land in Ubuntu for some time, as those guys are very conservative about the patches they will take to issues packages.

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

Successfully merging a pull request may close this issue.

4 participants