I’m having some issues accessing docker containers over my remote OpenVPN connection to my home Ubuntu Server 20.04 LTS.
My setup; I have a few docker containers (bridge mode) running on the same machine as the OpenVPN Access Server that I would like to access remotely without exposing access over the internet. I’ve successfully proved that the docker services can be accessed from outside the local network by temporarily exposing and forwarding those ports.
I am also able to successfully connect to other machines on the local subnet via the OpenVPN connection and access native service running on the OpenVPN host.
When attempting to access docker services running on the host machine, the request times out with no response.
My hunch is that IP tables on the host machine created by docker may be filtering out traffic from anything other than the local subnet (192.168.1.0/24 range), where VPN connections are assigned to a different subnet. This is the point I get a bit out of my depth!
I’ve listed below the OpenVPN config file (hopefully removing anything sensitive!), the relevant docker IP table rules and the results of the tests I have run so far. Hope you can help!
Timeout when attempting to access docker services on the host:
curl -sv http://192.168.1.x:8002 1> /dev/null
* Trying 192.168.1.x:8002...
* TCP_NODELAY set
* connect to 192.168.1.x port 8002 failed: Connection timed out
* Failed to connect to 192.168.1.x port 8002: Connection timed out
* Closing connection 0
Successful response conecting to a native service on the same host:
curl -sv http://{host IP}:{native service port} 1> /dev/null
* Trying 192.168.1.x:xxxx...
* TCP_NODELAY set
* Connected to 192.168.1.x (192.168.1.x) port xxxx (#0)
> GET / HTTP/1.1
> Host: 192.168.1.x:xxxx
> User-Agent: curl/7.65.3
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Length: 193
< Content-Type: text/html
< Connection: close
< Cache-Control: no-cache
< Date: Wed, 13 Jan 2021 01:39:12 GMT
<
{ (193 bytes data)
* Closing connection 0
Successful request to the docker service from the local subnet (no OpenVPN connection) :
curl -sv http://192.168.1.x:8002 1> /dev/null
* Trying 192.168.1.x:8002...
* TCP_NODELAY set
* Connected to 192.168.1.x (192.168.1.x) port 8002 (#0)
> GET / HTTP/1.1
> Host: 192.168.1.x:8002
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
***
<
{ (6324 bytes data)
* Connection #0 to host 192.168.1.x left intact
OpenVPN Config:
# OpenVPN AS 1.1 configuration file
# enable AS Connect functionality
AS_CONNECT=true
# temporary directory
tmp_dir=~/tmp
lic.dir=**REMOVED**
# run_start retries
run_start_retry.give_up=60
run_start_retry.resample=10
# enable client gateway
sa.show_c2s_routes=true
# certificates database
certs_db=**REMOVED**
# user properties DB
user_prop_db=**REMOVED**
# configuration DB
config_db=sqlite:**REMOVED**
# configuration DB Local
config_db_local=sqlite:**REMOVED**
# cluster DB
cluster_db=sqlite:**REMOVED**
# notification DB
notification_db=sqlite:**REMOVED**
# log DB
log_db=sqlite:**REMOVED**
# wait this many seconds between failed retries
db_retry.interval=1
# how many retries to attempt before failing
db_retry.n_attempts=6
# bootstrap authentication via PAM -- allows
# admin to log into web UI before authentication
# system has been configured. Configure PAM users
# allowed to access via the bootstrap auth mechanism.
boot_pam_service=openvpnas
boot_pam_users.0=openvpn
# boot_pam_users.1=
# boot_pam_users.2=
# boot_pam_users.3=
# boot_pam_users.4=
# System users that are allowed to access the server agent XML API.
# The user that the web server will run as should be in this list.
system_users_local.0=root
system_users_local.1=openvpn_as
# The user/group that the web server will run as
cs.user=openvpn_as
cs.group=openvpn_as
# socket directory
general.sock_dir=~/sock
# path to linux openvpn executable
# if undefined, find openvpn on the PATH
#general.openvpn_exe_path=
# source directory for OpenVPN Windows executable
# (Must have been built with MultiFileExtract)
sa.win_exe_dir=~/exe
# The company name will be shown in the UI
# sa.company_name=Access Server
# server agent socket
sa.sock=~/sock/sagent
# If enabled, automatically generate a client configuration
# when a client logs into the site and successfully authenticates
cs.auto_generate=true
# files for web server (PEM format)
cs.ca_bundle=~/web-ssl/ca.crt
cs.priv_key=~/web-ssl/server.key
cs.cert=~/web-ssl/server.crt
# web server will use three consecutive ports starting at this
# address, for use with the OpenVPN port share feature
cs.dynamic_port_base=870
# which service groups should be started during
# server agent initialization
sa.initial_run_groups.0=web_group
#sa.initial_run_groups.1=openvpn_group
# use this twisted reactor
sa.reactor=epoll
# The unit number of this particular AS configuration.
# Normally set to 0. If you have multiple, independent AS instances
# running on the same machine, each should have a unique unit number.
sa.unit=0
# If true, open up web ports on the firewall using iptables
iptables.web=true
vpn.server.user=openvpn_as
vpn.server.group=openvpn_as
IPTables Relevant Docker rules:
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.18.0.5 tcp dpt:http-alt
ACCEPT tcp -- anywhere 172.18.0.6 tcp dpt:http
()
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere