How to deny external ipv6 access to router web page

I am trying to get ipv6 working on my openwrt router and I have found a disturbing problem with the ipv6 access. When I access the router from an external ip address using its [router:ipv6:address], it connects. With Ipv4, it doesn’t. I don’t want anyone to be able to connect to the router itself from the outside.

Also, I want both ipv4 and ipv6 connects to the router from the external internet to be port forwarded to the web server on another machine. External connects should never connect to the router luci page. This was working with port forwarding with ipv4 and I created another rule that port forwards ipv6 traffic on port 80 to the web server.

So is there an easy way to block all external public traffic to luci, but still allow port forwards to local machines on the lan? But still allow access to luci from internal local lan ip addresses?

Thanks.

1 Like

From inside the network, this may be possible, but it will not be from outside... at least assuming you haven't changed things from their defaults with respect to the wan/wan6 interfaces and the firewall.

Did you test from outside your network (using a mobile phone on cellular, for example)?

Please connect to your OpenWrt device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button:
grafik
Remember to redact passwords, VPN keys, MAC addresses and any public IP addresses you may have:

ubus call system board
cat /etc/config/network
cat /etc/config/firewall
2 Likes

Also add output of

opkg list-installed | grep ^luci

It should be simple to switch uhttpd (or nginx) and dropbear (or openssh) to listen on ipv4 only or to localhost only)

I tried to use the preformatted thing, but it wasn't working right. Here are the requested files. I tried to redact everything,

Yes, I used my cell phone data interface to try to test the web server's ipv6 connection using the router's [::ip6::] direct address. I put in a rule to port forward ip6 port 80 traffic to the web server. The apache web server is a different machine and not on the router. I admit being ipv6 illiterate. Anyhow, instead of port forwarding the packet, it connected to LUCI on the router. That should not be allowed. I have not tried to see if SSH is also exposed, but it shouldn't be ether. With the exception of apache and asterisk, nothing else should be exposed to the web. Remote access is still possible, but only through wireguard. At least that's the way its supposed to work.

Requested data follows. Sorry if its not preformatted right.

ubus call system board
{
"kernel": "5.15.134",
"hostname": "Tomato",
"system": "ARMv7 Processor rev 1 (v7l)",
"model": "Linksys WRT1200AC",
"board_name": "linksys,wrt1200ac",
"rootfs_type": "squashfs",
"release": {
"distribution": "OpenWrt",
"version": "99.99.99",
"revision": "r23497-6637af95aa",
"target": "mvebu/cortexa9",
"description": "OpenWrt 99.99.99 r23497-6637af95aa"
}
}

cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fdf2:xxxx:xxxx::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        option macaddr 'zz:zz:zz:zz:xx:xx'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config device
        option name 'wan'
        option macaddr 'dd:dd:dd:dd:dd:dd'

config interface 'wan'
        option device 'wan'
        option proto 'dhcp'

config interface 'wan6'
        option device 'wan'
        option proto 'dhcpv6'

config device
        option name 'eth0'
        option macaddr 'dd:dd:dd:dd:dd:dd'

config interface 'vpn'
        option proto 'wireguard'
        option private_key 'This is not the real private key='
        option listen_port '99999'
        list addresses '192.168.xxx.yyy/24'

config wireguard_vpn 'wgclient'
        option public_key 'Not='
        option preshared_key 'The='
        option private_key 'real='
        list allowed_ips '192.168.xxx.yyy/32'
        option description 'Cell Phone Peer'

config interface 'CamLan'
        option proto 'static'
        option ipaddr '192.168.ggg.hhh'
        option netmask '255.255.255.0'
        option device 'lan1'

config wireguard_vpn
        option description 'OtherComputer'
        option public_key 'Not A='
        option private_key 'Real='
        option preshared_key 'KEY='
        list allowed_ips '192.168.xx.y/32'


cat /etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone 'lan'
        option name 'lan'
        list network 'lan'
        list network 'vpn'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'

config zone 'wan'
        option name 'wan'
        list network 'wan'
        list network 'wan6'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'Asterisk'
        option family 'ipv4'
        list proto 'udp'
        option src 'wan'
        option src_dport '9999-9999'
        option dest_ip '192.168.1.999'
        option dest_port '9999'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'AsteriskRTP'
        option family 'ipv4'
        list proto 'udp'
        option src 'wan'
        option src_dport '7777-7777'
        option dest_ip '192.168.1.999'
        option dest_port '77777-77777'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'Apache2_ipv4'
        option family 'ipv4'
        list proto 'tcp'
        option src 'wan'
        option src_dport '80'
        option dest_ip '192.168.1.9999'
        option dest_port '80'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'Apache2-IPv6'
        list proto 'tcp'
        option src 'wan'
        option src_dport '80'
        option dest_ip '2601:uuuu:yyyy::9999'
        option dest_port '80'
        option family 'ipv6'
        option enabled '0'

config rule 'wg'
        option name 'Allow-WireGuard'
        option src 'wan'
        option dest_port '99999'
        option proto 'udp'
        option target 'ACCEPT'

config zone
        option name 'CamWall'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'CamLan'

config forwarding
        option src 'CamWall'
        option dest 'lan'

config forwarding
        option src 'lan'
        option dest 'CamWall'

config rule
        option name 'Allow_BlueIrisOut'
        list src_ip '192.168.888.999'
        option dest '*'
        option target 'ACCEPT'
        option src 'CamWall'
        option enabled '0'

config rule
        option name 'Allow_BlueIrisIn'
        option src '*'
        option dest 'CamWall'
        list dest_ip '192.168.888.999'
        option target 'ACCEPT'
        option enabled '0'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'Apache2-Test'
        list proto 'tcp'
        option src 'wan'
        option src_dport '80'
        option dest_ip '192.168.1.999'
        option dest_port '80'
        option enabled '0'


opkg list-installed | grep ^luci
luci - git-23.051.66410-a505bb1
luci-app-ddns - git-23.346.52990-28c4a65
luci-app-firewall - git-23.208.40260-9504081
luci-app-opkg - git-23.009.82915-ec3aac4
luci-base - git-23.236.53405-fc638c8
luci-lib-base - git-22.308.54612-9118452
luci-lib-ip - git-23.311.79290-c2a887e
luci-lib-jsonc - git-23.298.74571-62eb535
luci-lib-nixio - git-24.034.54875-21210dc
luci-light - git-23.024.33244-34dee82
luci-lua-runtime - git-23.233.52805-dae2684
luci-mod-admin-full - git-19.253.48496-3f93650
luci-mod-network - git-23.283.21598-257f54c
luci-mod-status - git-23.236.53405-9b3c7d3
luci-mod-system - git-23.118.78765-58f7b27
luci-proto-ipv6 - git-21.148.48881-79947af
luci-proto-ppp - git-21.158.38888-88b9d84
luci-proto-wireguard - git-23.338.83621-1c2acbe
luci-ssl - git-23.035.26083-7550ad6
luci-theme-bootstrap - git-23.085.34270-d94a728

I'm using apache not nginx and its located on a separate machine. I still want IPv6 and IPv4 to work for everything its supposed to work on. There is also a camera server and cameras on the same network that are connected to a vlan that are blocked from all internet access (both directions), but accessible from wireguard and local addresses. At least that is the intention.

It seems that IPv6 is giving all my local devices a public IPv6 which is distressing. I want everything to go through the router without exception and nothing goes to a local device without the router explicitly allowing it.

I also ran an external port scan from a web site. I don't know what is going on here. This morning I'm getting all ports closed. Yesterday, http was open. So at least this says that ssh is closed.

I tried the web server's prefixed IPv6 address also and it also says everything is closed. But it shouldn't be. The web server should show port 80 open because there is a port forwarding rule for that.

Starting Nmap 7.80 ( https://nmap.org ) at 2025-10-15 11:37 UTC
Nmap scan report for 2001:558:zzzz:zzz:zzzz:wwww:wwww:wwww
Host is up (0.036s latency).

PORT     STATE  SERVICE       VERSION
21/tcp   closed ftp
22/tcp   closed ssh
23/tcp   closed telnet
80/tcp   closed http
110/tcp  closed pop3
143/tcp  closed imap
443/tcp  closed https
3389/tcp closed ms-wbt-server

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.75 seconds

Dude, thats the whole point. It was even so with IPv4. Rfc1918 and nat was only invented like 15 years later because the experiment escaped the universities lab.

3 Likes

Since IPv6 (configured as you have, which is the best way) does not NAT, access to a v6 web server on the LAN is simply a traffic rule forward, not a port forward.

config rule
   option name 'Allow_v6_http_servers'
   option family ipv6
   option src wan
   option dest lan
   option dest_port 80
   option proto tcp 

SInce this does not filter dest_ip, any and every LAN device listening on port 80 will be reachable from outside. You probably don't want that, so if the web server is at a constant IP you can add option dest_ip to constrain the rule to that one device. In many cases the ISP will change the first 64 bits of your line's V6 address on you, so there is the '/-64' syntax to filter on only the last 64 bits which you control.

4 Likes

That seemed to fix the issue with the web server. Thanks.

From inside the network:

curl -g -6 [my:redacted:ipv6:router:address]
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
                <meta http-equiv="Pragma" content="no-cache" />
                <meta http-equiv="Expires" content="0" />
                <meta http-equiv="refresh" content="0; URL=cgi-bin/luci/" />
                <style type="text/css">
                        body { background: white; font-family: arial, helvetica, sans-serif; }
                        a { color: black; }

                        @media (prefers-color-scheme: dark) {
                                body { background: black; }
                                a { color: white; }
                        }
                </style>
        </head>
        <body>
                <a href="cgi-bin/luci/">LuCI - Lua Configuration Interface</a>
        </body>
</html>

However, the online port scanner still shows the same IPv6 address as closed. I can live with it as long as nobody can access my router from the outside.