The tunnel comes up, the login succeeds, and every host on the network answers. That is not a broken VPN; it is a VPN with no permission model. RouterOS authenticates the account and then routes its packets like anyone else's, so the firewall has to supply the limit. Adding that limit without breaking the login is the whole job.

Authentication ends where permission begins

Once a PPP session is up, packets from the client enter the forward chain like traffic from any other interface. If the router's forward policy is permissive, the consultant inherits that permissiveness at login. The account never carried a scope, so there is nothing on the account to change. The rule set was written for employees and the new session simply joined it.

Check which path the request is about before writing anything. Traffic to hosts behind the router crosses forward, while traffic to the router itself, including winbox and SSH, crosses input. A scope that covers only forward leaves the device open to the same client.

Both chains need a decision, even if the decision is to leave input closed. That choice belongs in the access request, not in an afterthought.

Attach the session to a named list

A PPP profile can place the address it hands out into a named address list as the session starts. That converts a transient tunnel address into something the firewall can match by name, and the entry disappears when the session ends. The account then inherits the scope from its profile rather than from a rule that hard-codes an address.

Create the profile first, then bind the secret to it explicitly. A secret still pointing at the default profile reproduces the original problem.

Name the profile and the list so their jobs are obvious, and comment both with the request reference. One profile can serve several people with the same scope, while the list still identifies each live session. That is cheaper to review than a rule per person.

/ppp profile add name=scoped-consultant remote-address=consultant-pool address-list=vpn-scoped-clients
/ppp secret add name=consultant password=... service=ovpn profile=scoped-consultant

Record the allowed service in one list

Put the permitted server in its own address list instead of embedding the address in a filter rule. The list can be audited, extended and commented, and the rule that consumes it does not change when the server moves. A single entry looks like overkill until the second host arrives, which it usually does.

Match a list when the address is dynamic or load-balanced, and match the address directly when it is reserved and stable. Either choice reads clearly if the comment names the service and the owner.

Scope the protocol and the port as well as the host. An accept for a host with no port restriction opens every service that host runs, which is broader than most access requests intend. The port is part of the permission, not a detail to be added later.

/ip firewall address-list add list=vpn-targets address=10.0.0.10 comment="consultant RDP target"

Order the jump before any broad accept

A jump rule sends forwarded traffic from the scoped list into a private chain where the entire policy fits on three lines. The first rule accepts the permitted destination and port, and the last rule drops everything else. The jump must sit above any broad accept in forward, because an earlier accept means the jump never runs. Keep the established and related accept ahead of the jump so return traffic still flows.

Check that no fasttrack rule can carry this traffic past the scoped chain. Fasttrack bypasses the rest of the filter path, and a scoped session that is fasttracked is not scoped at all.

Repeat the decision for the input chain if the router's own services should be unreachable. A scope that blocks forwarded traffic and leaves winbox open is only half finished.

/ip firewall filter
add chain=forward action=jump jump-target=scoped-vpn src-address-list=vpn-scoped-clients
add chain=scoped-vpn action=accept protocol=tcp dst-address-list=vpn-targets dst-port=3389
add chain=scoped-vpn action=drop

Verify with counters and list membership

From the client, test the permitted service and one that must fail, then read the rule statistics on the router. The accept and drop counters show which path each packet took, which the client cannot see. Confirm as well that the live session address appeared in the scoped list.

An empty list means the account is on a different profile or the profile lost its address-list setting. A climbing drop counter with a failing permitted service means the destination or port does not match what the client sends.

Test the same service by name and by address before concluding anything. A name resolution failure looks exactly like a blocked port from the client side. Then record the profile, both lists and the single permitted service in the access request so the next review compares instead of reconstructing.

/ip firewall filter print stats where chain=scoped-vpn
/ip firewall address-list print where list=vpn-scoped-clients

Qillqakuna t'inkisqa