Note: I will consider that your router's LAN is 192.0.2.0/24 and its LAN IP on eth0 is 192.0.2.1/24, to be able to give concrete explanations and a solution.
Your ISP, to spare some public IP addresses, assigned you a private IPs for internal routing purpose. That's fine because this IP is never meant to be seen outside (and would be quickly dropped by Strict Reverse Path Forwarding along the path if ever put on the wire beyond your ISP router, or if not, since non-routable, will never get a reply). But this makes your configuration more complex to avoid having this IP to be used in all cases but connectivity to ISP, from your router.
You probably have something similar to this (it might be slightly different, doesn't matter):
# ip route
default via 10.0.0.9 dev ppp0
10.0.0.9 dev ppp0 proto kernel scope link src 10.0.0.10
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.1
It's possible for example that you have instead default via 10.0.0.9 dev ppp0 src 10.0.0.10 , or that via 10.0.0.9 doesn't even appear, since it's a layer 3 link rather than a layer 2 link, making via not needed (but still accepted). Just adapt the settings below accordingly.
Currently, the kernel chooses the apparently best suited IP, the one set on the same side to reach Internet, since nothing tells it otherwise (or it explicitly tells to use the IP you don't want):
# ip route get 8.8.8.8
8.8.8.8 via 10.0.0.9 dev ppp0 src 10.0.0.10 uid 0
cache
You just need to replace the routing behaviour when the kernel checks how to reach internet and state a specific preferred source IP address. Be aware that you might lose connectivity in case of errors and unforeseen problems. Have alternate (console) access if possible:
# ip route replace default via 10.0.0.9 dev ppp0 src 192.0.2.1
# ip route get 8.8.8.8
8.8.8.8 via 10.0.0.9 dev ppp0 src 192.0.2.1 uid 0
cache
That's it, your router will route as usual, but when needing to choose a locally originated outgoing IP, will select 192.0.2.1 unless explicitly told otherwise (eg: process binding explicitly the source IP on its socket).
This route must be set again each time the link is brought down then up. It's up to you to integrate this in some pppoe script, after the link is fully established.
Note also that the interface name ppp0 might change to ppp1 or any other name. That's up to you to deal with this in your setup scripts.
Alternate methods to set this same route setting:
- add a lower metric, when a metric is initially set
If the original metric was set (ie it wasn't 0, let's say it was 100), you can instead add an alternate default route with a lower metric rather than replacing the previous:
# ip route add default via 10.0.0.9 dev ppp0 src 192.0.2.1 metric 50
- dedicated routing rule
If you fear interaction from various tools involved in pppoe that might remove the route above, you can install this setting in an alternate routing table and give it precedence in routing rules, with a partial copy of the main table to prevent disruption. This will still have to be redone after each disconnection/reconnection, because the route will still disappear. Here iif lo is special and really means "locally originated outgoing packet" rather than incoming, and 109 is an arbitrary chosen table value:
# ip rule add iif lo lookup 109 # needed only once
# ip route add table 109 10.0.0.9 dev ppp0 proto kernel scope link src 10.0.0.10 # to keep using 10.0.0.10 for local link, just in case
# ip route add table 109 192.0.2.0/24 dev eth0 src 192.0.2.1 # will disappear if eth0 is brought down
# ip route add table 109 default via 10.0.0.9 dev ppp0 src 192.0.2.1 # will disappear if ppp0 is brought down
If you added other routing entries in the main table, chances are you'd also have to copy them above.
# ip route get 8.8.8.8
8.8.8.8 via 10.0.0.9 dev ppp0 table 109 src 192.0.2.1 uid 0
cache